<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qbsprojectmanagerplugin.h"

#include "qbsbuildconfiguration.h"
#include "qbsbuildstep.h"
#include "qbscleanstep.h"
#include "qbsdeployconfigurationfactory.h"
#include "qbsinstallstep.h"
#include "qbsnodes.h"
#include "qbsproject.h"
#include "qbsprojectmanager.h"
#include "qbsprojectmanagerconstants.h"
#include "qbsrunconfiguration.h"

#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/mimedatabase.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtsupportconstants.h>
#include <utils/qtcassert.h>

#include <QAction>
#include <QtPlugin>

namespace QbsProjectManager {
namespace Internal {

QbsProjectManagerPlugin::QbsProjectManagerPlugin() :
    m_manager(0),
    m_projectExplorer(0),
    m_currentProject(0),
    m_currentTarget(0),
    m_currentNode(0)
{ }

bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    Q_UNUSED(errorMessage);
    m_manager = new QbsManager(this);
    m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
    const Core::Context projectContext(::QbsProjectManager::Constants::PROJECT_ID);
    const Core::Context globalcontext(Core::Constants::C_GLOBAL);

    Q_UNUSED(arguments);

    Core::FileIconProvider::instance()
            ->registerIconOverlayForSuffix(QIcon(QLatin1String(QtSupport::Constants::ICON_QT_PROJECT)),
                                           QLatin1String("qbs"));

    //create and register objects
    addAutoReleasedObject(m_manager);
    addAutoReleasedObject(new QbsBuildConfigurationFactory);
    addAutoReleasedObject(new QbsBuildStepFactory);
    addAutoReleasedObject(new QbsCleanStepFactory);
    addAutoReleasedObject(new QbsInstallStepFactory);
    addAutoReleasedObject(new QbsDeployConfigurationFactory);
    addAutoReleasedObject(new QbsRunConfigurationFactory);

    //menus
    // Build Menu:
    Core::ActionContainer *mbuild =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
    // PE Context menu for projects
    Core::ActionContainer *mproject =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
    Core::ActionContainer *msubproject =
             Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
    Core::ActionContainer *mfile =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT);

    //register actions
    Core::Command *command;

    m_reparseQbs = new QAction(tr("Reparse Qbs"), this);
    command = Core::ActionManager::registerAction(m_reparseQbs, Constants::ACTION_REPARSE_QBS, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
    connect(m_reparseQbs, SIGNAL(triggered()), this, SLOT(reparseCurrentProject()));

    m_reparseQbsCtx = new QAction(tr("Reparse Qbs"), this);
    command = Core::ActionManager::registerAction(m_reparseQbsCtx, Constants::ACTION_REPARSE_QBS_CONTEXT, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_reparseQbsCtx, SIGNAL(triggered()), this, SLOT(reparseCurrentProject()));

    m_buildFileContextMenu = new QAction(tr("Build"), this);
    command = Core::ActionManager::registerAction(m_buildFileContextMenu, Constants::ACTION_BUILD_FILE_CONTEXT, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mfile->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER);
    connect(m_buildFileContextMenu, SIGNAL(triggered()), this, SLOT(buildFileContextMenu()));

    m_buildFile = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""),
                                                   Utils::ParameterAction::AlwaysEnabled, this);
    command = Core::ActionManager::registerAction(m_buildFile, Constants::ACTION_BUILD_FILE, globalcontext);
    command->setAttribute(Core::Command::CA_Hide);
    command->setAttribute(Core::Command::CA_UpdateText);
    command->setDescription(m_buildFile->text());
    command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+B")));
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
    connect(m_buildFile, SIGNAL(triggered()), this, SLOT(buildFile()));

    m_buildProductContextMenu = new QAction(tr("Build"), this);
    command = Core::ActionManager::registerAction(m_buildProductContextMenu, Constants::ACTION_BUILD_PRODUCT_CONTEXT, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_buildProductContextMenu, SIGNAL(triggered()), this, SLOT(buildProductContextMenu()));

    m_buildProduct = new Utils::ParameterAction(tr("Build Product"), tr("Build Product \"%1\""),
                                                Utils::ParameterAction::AlwaysEnabled, this);
    command = Core::ActionManager::registerAction(m_buildProduct, Constants::ACTION_BUILD_PRODUCT, globalcontext);
    command->setAttribute(Core::Command::CA_Hide);
    command->setAttribute(Core::Command::CA_UpdateText);
    command->setDescription(m_buildFile->text());
    command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Shift+B")));
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
    connect(m_buildProduct, SIGNAL(triggered()), this, SLOT(buildProduct()));

    // Connect
    connect(m_projectExplorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
            this, SLOT(updateContextActions(ProjectExplorer::Node*,ProjectExplorer::Project*)));

    connect(m_projectExplorer->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)),
            this, SLOT(buildStateChanged(ProjectExplorer::Project*)));

    connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
            this, SLOT(updateBuildActions()));

    // Run initial setup routines
    updateContextActions(0, 0);
    updateReparseQbsAction();
    updateBuildActions();

    return true;
}

void QbsProjectManagerPlugin::extensionsInitialized()
{ }

void QbsProjectManagerPlugin::updateContextActions(ProjectExplorer::Node *node, ProjectExplorer::Project *project)
{
    if (m_currentProject) {
        disconnect(m_currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
                   this, SLOT(activeTargetChanged()));
        disconnect(m_currentProject, SIGNAL(projectParsingStarted()),
                   this, SLOT(parsingStateChanged()));
        disconnect(m_currentProject, SIGNAL(projectParsingDone(bool)),
                   this, SLOT(parsingStateChanged()));
    }

    m_currentNode = node;
    m_currentProject = qobject_cast<Internal::QbsProject *>(project);
    if (m_currentProject) {
        connect(m_currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
                this, SLOT(activeTargetChanged()));
        connect(m_currentProject, SIGNAL(projectParsingStarted()),
                this, SLOT(parsingStateChanged()));
        connect(m_currentProject, SIGNAL(projectParsingDone(bool)),
                this, SLOT(parsingStateChanged()));
    }

    activeTargetChanged();

    bool isBuilding = m_projectExplorer->buildManager()->isBuilding(project);
    bool isFile = m_currentProject && node && (node->nodeType() == ProjectExplorer::FileNodeType);
    bool isProduct = m_currentProject && node && qobject_cast<QbsProductNode *>(node->projectNode());
    bool isFileEnabled = isFile && node->isEnabled();

    m_reparseQbsCtx->setEnabled(!isBuilding && m_currentProject && !m_currentProject->isParsing());
    m_buildFileContextMenu->setEnabled(isFileEnabled);
    m_buildProductContextMenu->setEnabled(isProduct);
}

void QbsProjectManagerPlugin::updateReparseQbsAction()
{
    m_reparseQbs->setEnabled(m_currentProject
                             && !m_projectExplorer->buildManager()->isBuilding(m_currentProject)
                             && !m_currentProject->isParsing());
}

void QbsProjectManagerPlugin::updateBuildActions()
{
    bool fileVisible = false;
    bool fileEnabled = false;
    bool productVisible = false;
    bool productEnabled = false;

    QString file;

    if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
        file = currentDocument->filePath();
        ProjectExplorer::SessionManager *session = m_projectExplorer->session();
        ProjectExplorer::Node *node  = session->nodeForFile(file);
        ProjectExplorer::Project *project
                = qobject_cast<QbsProject *>(session->projectForFile(file));

        m_buildFile->setParameter(QFileInfo(file).fileName());
        fileVisible = project && node && qobject_cast<QbsBaseProjectNode *>(node->projectNode());
        fileEnabled = !m_projectExplorer->buildManager()->isBuilding(project)
                && m_currentProject && !m_currentProject->isParsing();

        if (QbsProductNode *productNode
                = qobject_cast<QbsProductNode *>(node ? node->projectNode() : 0)) {
            productEnabled = true;
            productVisible = true;
            m_buildProduct->setParameter(productNode->displayName());
        }
    }

    m_buildFile->setEnabled(fileEnabled);
    m_buildFile->setVisible(fileVisible);

    m_buildProduct->setEnabled(productEnabled);
    m_buildProduct->setVisible(productVisible);
}

void QbsProjectManagerPlugin::activeTargetChanged()
{
    if (m_currentTarget)
        disconnect(m_currentTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
                   this, SLOT(updateReparseQbsAction()));

    m_currentTarget = m_currentProject ? m_currentProject->activeTarget() : 0;

    if (m_currentTarget)
        connect(m_currentTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
                this, SLOT(updateReparseQbsAction()));

    updateReparseQbsAction();
}

void QbsProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *project)
{
    if (project == m_currentProject) {
        updateReparseQbsAction();
        updateContextActions(m_currentNode, m_currentProject);
        updateBuildActions();
    }
}

void QbsProjectManagerPlugin::parsingStateChanged()
{
    if (m_currentProject) {
        updateReparseQbsAction();
        updateContextActions(m_currentNode, m_currentProject);
    }
}

void QbsProjectManagerPlugin::buildFileContextMenu()
{
    QTC_ASSERT(m_currentNode, return);
    QTC_ASSERT(m_currentProject, return);

    buildFiles(m_currentProject, QStringList(m_currentNode->path()));
}

void QbsProjectManagerPlugin::buildFile()
{
    QString file;
    QbsProject *project = 0;
    if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
        file = currentDocument->filePath();
        project = qobject_cast<QbsProject *>(m_projectExplorer->session()->projectForFile(file));
    }

    if (!project || file.isEmpty())
        return;

    buildFiles(project, QStringList(file));
}

void QbsProjectManagerPlugin::buildProductContextMenu()
{
    QTC_ASSERT(m_currentNode, return);
    QTC_ASSERT(m_currentProject, return);

    buildProducts(m_currentProject, QStringList(m_currentNode->displayName()));
}

void QbsProjectManagerPlugin::buildProduct()
{
    QbsProject *project = 0;
    QbsProductNode *product = 0;
    if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
        const QString file = currentDocument->filePath();
        ProjectExplorer::SessionManager *session = m_projectExplorer->session();

        project = qobject_cast<QbsProject *>(session->projectForFile(file));
        product = qobject_cast<QbsProductNode *>(session->nodeForFile(file)->projectNode());
    }

    if (!project || !product)
        return;

    buildProducts(project, QStringList(product->displayName()));
}

void QbsProjectManagerPlugin::buildFiles(QbsProject *project, const QStringList &files)
{
    QTC_ASSERT(project, return);
    QTC_ASSERT(!files.isEmpty(), return);

    ProjectExplorer::Target *t = project->activeTarget();
    if (!t)
        return;
    QbsBuildConfiguration *bc = qobject_cast<QbsBuildConfiguration *>(t->activeBuildConfiguration());
    if (!bc)
        return;

    ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
    if (!pe->saveModifiedFiles())
        return;

    bc->setChangedFiles(files);
    bc->setProducts(QStringList());

    const Core::Id buildStep = Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD);

    const QString name = ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(buildStep);
    pe->buildManager()->buildList(bc->stepList(buildStep), name);

    bc->setChangedFiles(QStringList());
}

void QbsProjectManagerPlugin::buildProducts(QbsProject *project, const QStringList &products)
{
    QTC_ASSERT(project, return);
    QTC_ASSERT(!products.isEmpty(), return);

    ProjectExplorer::Target *t = project->activeTarget();
    if (!t)
        return;
    QbsBuildConfiguration *bc = qobject_cast<QbsBuildConfiguration *>(t->activeBuildConfiguration());
    if (!bc)
        return;

    ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
    if (!pe->saveModifiedFiles())
        return;

    bc->setChangedFiles(QStringList());
    bc->setProducts(products);

    const Core::Id buildStep = Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD);

    const QString name = ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(buildStep);
    pe->buildManager()->buildList(bc->stepList(buildStep), name);

    bc->setProducts(QStringList());
}

void QbsProjectManagerPlugin::reparseCurrentProject()
{
    if (m_currentProject)
        m_currentProject->parseCurrentBuildConfiguration();
}

} // namespace Internal
} // namespace QbsProjectManager

Q_EXPORT_PLUGIN(QbsProjectManager::Internal::QbsProjectManagerPlugin)
<commit_msg>Qbs: Small header cleanup<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qbsprojectmanagerplugin.h"

#include "qbsbuildconfiguration.h"
#include "qbsbuildstep.h"
#include "qbscleanstep.h"
#include "qbsdeployconfigurationfactory.h"
#include "qbsinstallstep.h"
#include "qbsnodes.h"
#include "qbsproject.h"
#include "qbsprojectmanager.h"
#include "qbsprojectmanagerconstants.h"
#include "qbsrunconfiguration.h"

#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/fileiconprovider.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtsupportconstants.h>
#include <utils/qtcassert.h>

#include <QAction>
#include <QtPlugin>

namespace QbsProjectManager {
namespace Internal {

QbsProjectManagerPlugin::QbsProjectManagerPlugin() :
    m_manager(0),
    m_projectExplorer(0),
    m_currentProject(0),
    m_currentTarget(0),
    m_currentNode(0)
{ }

bool QbsProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    Q_UNUSED(errorMessage);
    m_manager = new QbsManager(this);
    m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
    const Core::Context projectContext(::QbsProjectManager::Constants::PROJECT_ID);
    const Core::Context globalcontext(Core::Constants::C_GLOBAL);

    Q_UNUSED(arguments);

    Core::FileIconProvider::instance()
            ->registerIconOverlayForSuffix(QIcon(QLatin1String(QtSupport::Constants::ICON_QT_PROJECT)),
                                           QLatin1String("qbs"));

    //create and register objects
    addAutoReleasedObject(m_manager);
    addAutoReleasedObject(new QbsBuildConfigurationFactory);
    addAutoReleasedObject(new QbsBuildStepFactory);
    addAutoReleasedObject(new QbsCleanStepFactory);
    addAutoReleasedObject(new QbsInstallStepFactory);
    addAutoReleasedObject(new QbsDeployConfigurationFactory);
    addAutoReleasedObject(new QbsRunConfigurationFactory);

    //menus
    // Build Menu:
    Core::ActionContainer *mbuild =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
    // PE Context menu for projects
    Core::ActionContainer *mproject =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
    Core::ActionContainer *msubproject =
             Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
    Core::ActionContainer *mfile =
            Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT);

    //register actions
    Core::Command *command;

    m_reparseQbs = new QAction(tr("Reparse Qbs"), this);
    command = Core::ActionManager::registerAction(m_reparseQbs, Constants::ACTION_REPARSE_QBS, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
    connect(m_reparseQbs, SIGNAL(triggered()), this, SLOT(reparseCurrentProject()));

    m_reparseQbsCtx = new QAction(tr("Reparse Qbs"), this);
    command = Core::ActionManager::registerAction(m_reparseQbsCtx, Constants::ACTION_REPARSE_QBS_CONTEXT, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_reparseQbsCtx, SIGNAL(triggered()), this, SLOT(reparseCurrentProject()));

    m_buildFileContextMenu = new QAction(tr("Build"), this);
    command = Core::ActionManager::registerAction(m_buildFileContextMenu, Constants::ACTION_BUILD_FILE_CONTEXT, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mfile->addAction(command, ProjectExplorer::Constants::G_FILE_OTHER);
    connect(m_buildFileContextMenu, SIGNAL(triggered()), this, SLOT(buildFileContextMenu()));

    m_buildFile = new Utils::ParameterAction(tr("Build File"), tr("Build File \"%1\""),
                                                   Utils::ParameterAction::AlwaysEnabled, this);
    command = Core::ActionManager::registerAction(m_buildFile, Constants::ACTION_BUILD_FILE, globalcontext);
    command->setAttribute(Core::Command::CA_Hide);
    command->setAttribute(Core::Command::CA_UpdateText);
    command->setDescription(m_buildFile->text());
    command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+B")));
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
    connect(m_buildFile, SIGNAL(triggered()), this, SLOT(buildFile()));

    m_buildProductContextMenu = new QAction(tr("Build"), this);
    command = Core::ActionManager::registerAction(m_buildProductContextMenu, Constants::ACTION_BUILD_PRODUCT_CONTEXT, projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_buildProductContextMenu, SIGNAL(triggered()), this, SLOT(buildProductContextMenu()));

    m_buildProduct = new Utils::ParameterAction(tr("Build Product"), tr("Build Product \"%1\""),
                                                Utils::ParameterAction::AlwaysEnabled, this);
    command = Core::ActionManager::registerAction(m_buildProduct, Constants::ACTION_BUILD_PRODUCT, globalcontext);
    command->setAttribute(Core::Command::CA_Hide);
    command->setAttribute(Core::Command::CA_UpdateText);
    command->setDescription(m_buildFile->text());
    command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Shift+B")));
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
    connect(m_buildProduct, SIGNAL(triggered()), this, SLOT(buildProduct()));

    // Connect
    connect(m_projectExplorer, SIGNAL(currentNodeChanged(ProjectExplorer::Node*,ProjectExplorer::Project*)),
            this, SLOT(updateContextActions(ProjectExplorer::Node*,ProjectExplorer::Project*)));

    connect(m_projectExplorer->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)),
            this, SLOT(buildStateChanged(ProjectExplorer::Project*)));

    connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
            this, SLOT(updateBuildActions()));

    // Run initial setup routines
    updateContextActions(0, 0);
    updateReparseQbsAction();
    updateBuildActions();

    return true;
}

void QbsProjectManagerPlugin::extensionsInitialized()
{ }

void QbsProjectManagerPlugin::updateContextActions(ProjectExplorer::Node *node, ProjectExplorer::Project *project)
{
    if (m_currentProject) {
        disconnect(m_currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
                   this, SLOT(activeTargetChanged()));
        disconnect(m_currentProject, SIGNAL(projectParsingStarted()),
                   this, SLOT(parsingStateChanged()));
        disconnect(m_currentProject, SIGNAL(projectParsingDone(bool)),
                   this, SLOT(parsingStateChanged()));
    }

    m_currentNode = node;
    m_currentProject = qobject_cast<Internal::QbsProject *>(project);
    if (m_currentProject) {
        connect(m_currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
                this, SLOT(activeTargetChanged()));
        connect(m_currentProject, SIGNAL(projectParsingStarted()),
                this, SLOT(parsingStateChanged()));
        connect(m_currentProject, SIGNAL(projectParsingDone(bool)),
                this, SLOT(parsingStateChanged()));
    }

    activeTargetChanged();

    bool isBuilding = m_projectExplorer->buildManager()->isBuilding(project);
    bool isFile = m_currentProject && node && (node->nodeType() == ProjectExplorer::FileNodeType);
    bool isProduct = m_currentProject && node && qobject_cast<QbsProductNode *>(node->projectNode());
    bool isFileEnabled = isFile && node->isEnabled();

    m_reparseQbsCtx->setEnabled(!isBuilding && m_currentProject && !m_currentProject->isParsing());
    m_buildFileContextMenu->setEnabled(isFileEnabled);
    m_buildProductContextMenu->setEnabled(isProduct);
}

void QbsProjectManagerPlugin::updateReparseQbsAction()
{
    m_reparseQbs->setEnabled(m_currentProject
                             && !m_projectExplorer->buildManager()->isBuilding(m_currentProject)
                             && !m_currentProject->isParsing());
}

void QbsProjectManagerPlugin::updateBuildActions()
{
    bool fileVisible = false;
    bool fileEnabled = false;
    bool productVisible = false;
    bool productEnabled = false;

    QString file;

    if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
        file = currentDocument->filePath();
        ProjectExplorer::SessionManager *session = m_projectExplorer->session();
        ProjectExplorer::Node *node  = session->nodeForFile(file);
        ProjectExplorer::Project *project
                = qobject_cast<QbsProject *>(session->projectForFile(file));

        m_buildFile->setParameter(QFileInfo(file).fileName());
        fileVisible = project && node && qobject_cast<QbsBaseProjectNode *>(node->projectNode());
        fileEnabled = !m_projectExplorer->buildManager()->isBuilding(project)
                && m_currentProject && !m_currentProject->isParsing();

        if (QbsProductNode *productNode
                = qobject_cast<QbsProductNode *>(node ? node->projectNode() : 0)) {
            productEnabled = true;
            productVisible = true;
            m_buildProduct->setParameter(productNode->displayName());
        }
    }

    m_buildFile->setEnabled(fileEnabled);
    m_buildFile->setVisible(fileVisible);

    m_buildProduct->setEnabled(productEnabled);
    m_buildProduct->setVisible(productVisible);
}

void QbsProjectManagerPlugin::activeTargetChanged()
{
    if (m_currentTarget)
        disconnect(m_currentTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
                   this, SLOT(updateReparseQbsAction()));

    m_currentTarget = m_currentProject ? m_currentProject->activeTarget() : 0;

    if (m_currentTarget)
        connect(m_currentTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
                this, SLOT(updateReparseQbsAction()));

    updateReparseQbsAction();
}

void QbsProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *project)
{
    if (project == m_currentProject) {
        updateReparseQbsAction();
        updateContextActions(m_currentNode, m_currentProject);
        updateBuildActions();
    }
}

void QbsProjectManagerPlugin::parsingStateChanged()
{
    if (m_currentProject) {
        updateReparseQbsAction();
        updateContextActions(m_currentNode, m_currentProject);
    }
}

void QbsProjectManagerPlugin::buildFileContextMenu()
{
    QTC_ASSERT(m_currentNode, return);
    QTC_ASSERT(m_currentProject, return);

    buildFiles(m_currentProject, QStringList(m_currentNode->path()));
}

void QbsProjectManagerPlugin::buildFile()
{
    QString file;
    QbsProject *project = 0;
    if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
        file = currentDocument->filePath();
        project = qobject_cast<QbsProject *>(m_projectExplorer->session()->projectForFile(file));
    }

    if (!project || file.isEmpty())
        return;

    buildFiles(project, QStringList(file));
}

void QbsProjectManagerPlugin::buildProductContextMenu()
{
    QTC_ASSERT(m_currentNode, return);
    QTC_ASSERT(m_currentProject, return);

    buildProducts(m_currentProject, QStringList(m_currentNode->displayName()));
}

void QbsProjectManagerPlugin::buildProduct()
{
    QbsProject *project = 0;
    QbsProductNode *product = 0;
    if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
        const QString file = currentDocument->filePath();
        ProjectExplorer::SessionManager *session = m_projectExplorer->session();

        project = qobject_cast<QbsProject *>(session->projectForFile(file));
        product = qobject_cast<QbsProductNode *>(session->nodeForFile(file)->projectNode());
    }

    if (!project || !product)
        return;

    buildProducts(project, QStringList(product->displayName()));
}

void QbsProjectManagerPlugin::buildFiles(QbsProject *project, const QStringList &files)
{
    QTC_ASSERT(project, return);
    QTC_ASSERT(!files.isEmpty(), return);

    ProjectExplorer::Target *t = project->activeTarget();
    if (!t)
        return;
    QbsBuildConfiguration *bc = qobject_cast<QbsBuildConfiguration *>(t->activeBuildConfiguration());
    if (!bc)
        return;

    ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
    if (!pe->saveModifiedFiles())
        return;

    bc->setChangedFiles(files);
    bc->setProducts(QStringList());

    const Core::Id buildStep = Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD);

    const QString name = ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(buildStep);
    pe->buildManager()->buildList(bc->stepList(buildStep), name);

    bc->setChangedFiles(QStringList());
}

void QbsProjectManagerPlugin::buildProducts(QbsProject *project, const QStringList &products)
{
    QTC_ASSERT(project, return);
    QTC_ASSERT(!products.isEmpty(), return);

    ProjectExplorer::Target *t = project->activeTarget();
    if (!t)
        return;
    QbsBuildConfiguration *bc = qobject_cast<QbsBuildConfiguration *>(t->activeBuildConfiguration());
    if (!bc)
        return;

    ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance();
    if (!pe->saveModifiedFiles())
        return;

    bc->setChangedFiles(QStringList());
    bc->setProducts(products);

    const Core::Id buildStep = Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD);

    const QString name = ProjectExplorer::ProjectExplorerPlugin::displayNameForStepId(buildStep);
    pe->buildManager()->buildList(bc->stepList(buildStep), name);

    bc->setProducts(QStringList());
}

void QbsProjectManagerPlugin::reparseCurrentProject()
{
    if (m_currentProject)
        m_currentProject->parseCurrentBuildConfiguration();
}

} // namespace Internal
} // namespace QbsProjectManager

Q_EXPORT_PLUGIN(QbsProjectManager::Internal::QbsProjectManagerPlugin)
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qt4projectmanagerplugin.h"

#include "qt4projectmanager.h"
#include "qmakestep.h"
#include "makestep.h"
#include "wizards/consoleappwizard.h"
#include "wizards/guiappwizard.h"
#include "wizards/mobileappwizard.h"
#include "wizards/librarywizard.h"
#include "wizards/testwizard.h"
#include "wizards/emptyprojectwizard.h"
#include "wizards/qmlstandaloneappwizard.h"
#include "customwidgetwizard/customwidgetwizard.h"
#include "profileeditorfactory.h"
#include "qt4projectmanagerconstants.h"
#include "qt4project.h"
#include "qt4runconfiguration.h"
#include "profileeditor.h"
#include "profilereader.h"
#include "qtversionmanager.h"
#include "qtoptionspage.h"
#include "externaleditors.h"
#include "gettingstartedwelcomepage.h"

#include "qt-maemo/maemomanager.h"
#include "qt-s60/s60manager.h"

#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h>

#ifdef WITH_TESTS
#    include <QTest>
#endif

#include <QtCore/QtPlugin>

using namespace Qt4ProjectManager::Internal;
using namespace Qt4ProjectManager;
using ProjectExplorer::Project;

Qt4ProjectManagerPlugin::~Qt4ProjectManagerPlugin()
{
    //removeObject(m_embeddedPropertiesPage);
    //delete m_embeddedPropertiesPage;

    removeObject(m_proFileEditorFactory);
    delete m_proFileEditorFactory;
    removeObject(m_qt4ProjectManager);
    delete m_qt4ProjectManager;
    removeObject(m_welcomePage);
    delete m_welcomePage;
}

bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    Q_UNUSED(arguments)
    m_projectContext = Core::Context(Qt4ProjectManager::Constants::PROJECT_ID);

    ProFileParser::initialize();
    ProFileEvaluator::initialize();

    Core::ICore *core = Core::ICore::instance();
    if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":qt4projectmanager/Qt4ProjectManager.mimetypes.xml"), errorMessage))
        return false;

    m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
    Core::ActionManager *am = core->actionManager();

    QtVersionManager *mgr = new QtVersionManager;
    addAutoReleasedObject(mgr);
    addAutoReleasedObject(new QtOptionsPage);

    m_welcomePage = new GettingStartedWelcomePage;
    addObject(m_welcomePage);
    connect(mgr, SIGNAL(updateExamples(QString,QString,QString)),
            m_welcomePage, SLOT(updateExamples(QString,QString,QString)));

    //create and register objects
    m_qt4ProjectManager = new Qt4Manager(this);
    addObject(m_qt4ProjectManager);

    TextEditor::TextEditorActionHandler *editorHandler
            = new TextEditor::TextEditorActionHandler(Constants::C_PROFILEEDITOR,
                  TextEditor::TextEditorActionHandler::UnCommentSelection);

    m_proFileEditorFactory = new ProFileEditorFactory(m_qt4ProjectManager, editorHandler);
    addObject(m_proFileEditorFactory);

    addAutoReleasedObject(new EmptyProjectWizard);

    GuiAppWizard *guiWizard = new GuiAppWizard;
    addAutoReleasedObject(guiWizard);

    ConsoleAppWizard *consoleWizard = new ConsoleAppWizard;
    addAutoReleasedObject(consoleWizard);

    MobileAppWizard *mobileWizard = new MobileAppWizard;
    addAutoReleasedObject(mobileWizard);

    addAutoReleasedObject(new QmlStandaloneAppWizard());

    LibraryWizard *libWizard = new LibraryWizard;
    addAutoReleasedObject(libWizard);
    addAutoReleasedObject(new TestWizard);
    addAutoReleasedObject(new CustomWidgetWizard);

    CustomQt4ProjectWizard::registerSelf();

    addAutoReleasedObject(new QMakeStepFactory);
    addAutoReleasedObject(new MakeStepFactory);

    addAutoReleasedObject(new Qt4RunConfigurationFactory);

#ifdef Q_OS_MAC
    addAutoReleasedObject(new MacDesignerExternalEditor);
#else
    addAutoReleasedObject(new DesignerExternalEditor);
#endif
    addAutoReleasedObject(new LinguistExternalEditor);

    addAutoReleasedObject(new S60Manager);
    addAutoReleasedObject(new MaemoManager);

    new ProFileCacheManager(this);

    // TODO reenable
    //m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
    //addObject(m_embeddedPropertiesPage);

    //menus
    Core::ActionContainer *mbuild =
            am->actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
    Core::ActionContainer *mproject =
            am->actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
    Core::ActionContainer *msubproject =
            am->actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);

    //register actions
    Core::Command *command;

    QIcon qmakeIcon(QLatin1String(":/qt4projectmanager/images/run_qmake.png"));
    qmakeIcon.addFile(QLatin1String(":/qt4projectmanager/images/run_qmake_small.png"));
    m_runQMakeAction = new QAction(qmakeIcon, tr("Run qmake"), this);
    command = am->registerAction(m_runQMakeAction, Constants::RUNQMAKE, m_projectContext);
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PROJECT);
    connect(m_runQMakeAction, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(runQMake()));

    m_runQMakeActionContextMenu = new QAction(qmakeIcon, tr("Run qmake"), this);
    command = am->registerAction(m_runQMakeActionContextMenu, Constants::RUNQMAKECONTEXTMENU, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_runQMakeActionContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(runQMakeContextMenu()));

    QIcon buildIcon(ProjectExplorer::Constants::ICON_BUILD);
    buildIcon.addFile(ProjectExplorer::Constants::ICON_BUILD_SMALL);
    m_buildSubProjectContextMenu = new QAction(buildIcon, tr("Build"), this);
    command = am->registerAction(m_buildSubProjectContextMenu, Constants::BUILDSUBDIR, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_buildSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(buildSubDirContextMenu()));

    QIcon rebuildIcon(ProjectExplorer::Constants::ICON_REBUILD);
    rebuildIcon.addFile(ProjectExplorer::Constants::ICON_REBUILD_SMALL);
    m_rebuildSubProjectContextMenu = new QAction(rebuildIcon, tr("Rebuild"), this);
    command = am->registerAction(m_rebuildSubProjectContextMenu, Constants::REBUILDSUBDIR, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_rebuildSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(rebuildSubDirContextMenu()));

    QIcon cleanIcon(ProjectExplorer::Constants::ICON_CLEAN);
    cleanIcon.addFile(ProjectExplorer::Constants::ICON_CLEAN_SMALL);
    m_cleanSubProjectContextMenu = new QAction(cleanIcon, tr("Clean"), this);
    command = am->registerAction(m_cleanSubProjectContextMenu, Constants::CLEANSUBDIR, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_cleanSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(cleanSubDirContextMenu()));

    connect(m_projectExplorer,
            SIGNAL(aboutToShowContextMenu(ProjectExplorer::Project*, ProjectExplorer::Node*)),
            this, SLOT(updateContextMenu(ProjectExplorer::Project*, ProjectExplorer::Node*)));

    connect(m_projectExplorer->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project *)),
            this, SLOT(buildStateChanged(ProjectExplorer::Project *)));
    connect(m_projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project *)),
            this, SLOT(currentProjectChanged()));

    Core::ActionContainer *contextMenu = am->createMenu(Qt4ProjectManager::Constants::M_CONTEXT);

    Core::Command *cmd;

    Core::Context proFileEditorContext = Core::Context(Qt4ProjectManager::Constants::PROJECT_ID);

    QAction *jumpToFile = new QAction(tr("Jump to File Under Cursor"), this);
    cmd = am->registerAction(jumpToFile,
        Constants::JUMP_TO_FILE, proFileEditorContext);
    cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
    connect(jumpToFile, SIGNAL(triggered()),
            this, SLOT(jumpToFile()));
    contextMenu->addAction(cmd);

    QAction *addLibrary = new QAction(tr("Add Library..."), this);
    cmd = am->registerAction(addLibrary,
        Constants::ADDLIBRARY, proFileEditorContext);
    connect(addLibrary, SIGNAL(triggered()),
            this, SLOT(addLibrary()));
    contextMenu->addAction(cmd);

    QAction *separator = new QAction(this);
    separator->setSeparator(true);
    contextMenu->addAction(am->registerAction(separator,
                  Core::Id(Constants::SEPARATOR), proFileEditorContext));

    cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
    contextMenu->addAction(cmd);

    return true;
}

void Qt4ProjectManagerPlugin::extensionsInitialized()
{
    m_qt4ProjectManager->init();
}

void Qt4ProjectManagerPlugin::updateContextMenu(Project *project,
                                                ProjectExplorer::Node *node)
{
    m_qt4ProjectManager->setContextProject(project);
    m_qt4ProjectManager->setContextNode(node);
    m_runQMakeActionContextMenu->setEnabled(false);
    m_buildSubProjectContextMenu->setEnabled(false);
    m_rebuildSubProjectContextMenu->setEnabled(false);
    m_cleanSubProjectContextMenu->setEnabled(false);

    Qt4ProFileNode *proFileNode = qobject_cast<Qt4ProFileNode *>(node);
    if (qobject_cast<Qt4Project *>(project) && proFileNode) {
        m_runQMakeActionContextMenu->setVisible(true);
        m_buildSubProjectContextMenu->setVisible(true);
        m_rebuildSubProjectContextMenu->setVisible(true);
        m_cleanSubProjectContextMenu->setVisible(true);

        if (!m_projectExplorer->buildManager()->isBuilding(project)) {
            m_runQMakeActionContextMenu->setEnabled(true);
            m_buildSubProjectContextMenu->setEnabled(true);
            m_rebuildSubProjectContextMenu->setEnabled(true);
            m_cleanSubProjectContextMenu->setEnabled(true);
        }
    } else {
        m_runQMakeActionContextMenu->setVisible(false);
        m_buildSubProjectContextMenu->setVisible(false);
        m_rebuildSubProjectContextMenu->setVisible(false);
        m_cleanSubProjectContextMenu->setVisible(false);
    }
}

void Qt4ProjectManagerPlugin::currentProjectChanged()
{
    m_runQMakeAction->setEnabled(!m_projectExplorer->buildManager()->isBuilding(m_projectExplorer->currentProject()));
}

void Qt4ProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *pro)
{
    ProjectExplorer::Project *currentProject = m_projectExplorer->currentProject();
    if (pro == currentProject)
        m_runQMakeAction->setEnabled(!m_projectExplorer->buildManager()->isBuilding(currentProject));
    if (pro == m_qt4ProjectManager->contextProject())
        m_runQMakeActionContextMenu->setEnabled(!m_projectExplorer->buildManager()->isBuilding(pro));
}

void Qt4ProjectManagerPlugin::addLibrary()
{
    Core::EditorManager *em = Core::EditorManager::instance();
    ProFileEditor *editor = qobject_cast<ProFileEditor*>(em->currentEditor()->widget());
    if (editor)
        editor->addLibrary();
}

void Qt4ProjectManagerPlugin::jumpToFile()
{
    Core::EditorManager *em = Core::EditorManager::instance();
    ProFileEditor *editor = qobject_cast<ProFileEditor*>(em->currentEditor()->widget());
    if (editor)
        editor->jumpToFile();
}

#ifdef WITH_TESTS
void Qt4ProjectManagerPlugin::testBasicProjectLoading()
{
    QString testDirectory = ExtensionSystem::PluginManager::instance()->testDataDirectory() + "/qt4projectmanager/";
    QString test1 = testDirectory + "test1/test1.pro";
    m_projectExplorer->openProject(test1);
    QVERIFY(!m_projectExplorer->session()->projects().isEmpty());
    Qt4Project *qt4project = qobject_cast<Qt4Project *>(m_projectExplorer->session()->projects().first());
    QVERIFY(qt4project);
    QVERIFY(qt4project->rootProjectNode()->projectType() == ApplicationTemplate);
    QVERIFY(m_projectExplorer->currentProject() != 0);
}
#endif

Q_EXPORT_PLUGIN(Qt4ProjectManagerPlugin)
<commit_msg>Profile editor: Fix ambiguous shortcut F2.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qt4projectmanagerplugin.h"

#include "qt4projectmanager.h"
#include "qmakestep.h"
#include "makestep.h"
#include "wizards/consoleappwizard.h"
#include "wizards/guiappwizard.h"
#include "wizards/mobileappwizard.h"
#include "wizards/librarywizard.h"
#include "wizards/testwizard.h"
#include "wizards/emptyprojectwizard.h"
#include "wizards/qmlstandaloneappwizard.h"
#include "customwidgetwizard/customwidgetwizard.h"
#include "profileeditorfactory.h"
#include "qt4projectmanagerconstants.h"
#include "qt4project.h"
#include "qt4runconfiguration.h"
#include "profileeditor.h"
#include "profilereader.h"
#include "qtversionmanager.h"
#include "qtoptionspage.h"
#include "externaleditors.h"
#include "gettingstartedwelcomepage.h"

#include "qt-maemo/maemomanager.h"
#include "qt-s60/s60manager.h"

#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/texteditorconstants.h>

#ifdef WITH_TESTS
#    include <QTest>
#endif

#include <QtCore/QtPlugin>

using namespace Qt4ProjectManager::Internal;
using namespace Qt4ProjectManager;
using ProjectExplorer::Project;

Qt4ProjectManagerPlugin::~Qt4ProjectManagerPlugin()
{
    //removeObject(m_embeddedPropertiesPage);
    //delete m_embeddedPropertiesPage;

    removeObject(m_proFileEditorFactory);
    delete m_proFileEditorFactory;
    removeObject(m_qt4ProjectManager);
    delete m_qt4ProjectManager;
    removeObject(m_welcomePage);
    delete m_welcomePage;
}

bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *errorMessage)
{
    Q_UNUSED(arguments)
    m_projectContext = Core::Context(Qt4ProjectManager::Constants::PROJECT_ID);

    ProFileParser::initialize();
    ProFileEvaluator::initialize();

    Core::ICore *core = Core::ICore::instance();
    if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":qt4projectmanager/Qt4ProjectManager.mimetypes.xml"), errorMessage))
        return false;

    m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
    Core::ActionManager *am = core->actionManager();

    QtVersionManager *mgr = new QtVersionManager;
    addAutoReleasedObject(mgr);
    addAutoReleasedObject(new QtOptionsPage);

    m_welcomePage = new GettingStartedWelcomePage;
    addObject(m_welcomePage);
    connect(mgr, SIGNAL(updateExamples(QString,QString,QString)),
            m_welcomePage, SLOT(updateExamples(QString,QString,QString)));

    //create and register objects
    m_qt4ProjectManager = new Qt4Manager(this);
    addObject(m_qt4ProjectManager);

    TextEditor::TextEditorActionHandler *editorHandler
            = new TextEditor::TextEditorActionHandler(Constants::C_PROFILEEDITOR,
                  TextEditor::TextEditorActionHandler::UnCommentSelection);

    m_proFileEditorFactory = new ProFileEditorFactory(m_qt4ProjectManager, editorHandler);
    addObject(m_proFileEditorFactory);

    addAutoReleasedObject(new EmptyProjectWizard);

    GuiAppWizard *guiWizard = new GuiAppWizard;
    addAutoReleasedObject(guiWizard);

    ConsoleAppWizard *consoleWizard = new ConsoleAppWizard;
    addAutoReleasedObject(consoleWizard);

    MobileAppWizard *mobileWizard = new MobileAppWizard;
    addAutoReleasedObject(mobileWizard);

    addAutoReleasedObject(new QmlStandaloneAppWizard());

    LibraryWizard *libWizard = new LibraryWizard;
    addAutoReleasedObject(libWizard);
    addAutoReleasedObject(new TestWizard);
    addAutoReleasedObject(new CustomWidgetWizard);

    CustomQt4ProjectWizard::registerSelf();

    addAutoReleasedObject(new QMakeStepFactory);
    addAutoReleasedObject(new MakeStepFactory);

    addAutoReleasedObject(new Qt4RunConfigurationFactory);

#ifdef Q_OS_MAC
    addAutoReleasedObject(new MacDesignerExternalEditor);
#else
    addAutoReleasedObject(new DesignerExternalEditor);
#endif
    addAutoReleasedObject(new LinguistExternalEditor);

    addAutoReleasedObject(new S60Manager);
    addAutoReleasedObject(new MaemoManager);

    new ProFileCacheManager(this);

    // TODO reenable
    //m_embeddedPropertiesPage = new EmbeddedPropertiesPage;
    //addObject(m_embeddedPropertiesPage);

    //menus
    Core::ActionContainer *mbuild =
            am->actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
    Core::ActionContainer *mproject =
            am->actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT);
    Core::ActionContainer *msubproject =
            am->actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);

    //register actions
    Core::Command *command;

    QIcon qmakeIcon(QLatin1String(":/qt4projectmanager/images/run_qmake.png"));
    qmakeIcon.addFile(QLatin1String(":/qt4projectmanager/images/run_qmake_small.png"));
    m_runQMakeAction = new QAction(qmakeIcon, tr("Run qmake"), this);
    command = am->registerAction(m_runQMakeAction, Constants::RUNQMAKE, m_projectContext);
    mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_PROJECT);
    connect(m_runQMakeAction, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(runQMake()));

    m_runQMakeActionContextMenu = new QAction(qmakeIcon, tr("Run qmake"), this);
    command = am->registerAction(m_runQMakeActionContextMenu, Constants::RUNQMAKECONTEXTMENU, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    mproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_runQMakeActionContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(runQMakeContextMenu()));

    QIcon buildIcon(ProjectExplorer::Constants::ICON_BUILD);
    buildIcon.addFile(ProjectExplorer::Constants::ICON_BUILD_SMALL);
    m_buildSubProjectContextMenu = new QAction(buildIcon, tr("Build"), this);
    command = am->registerAction(m_buildSubProjectContextMenu, Constants::BUILDSUBDIR, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_buildSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(buildSubDirContextMenu()));

    QIcon rebuildIcon(ProjectExplorer::Constants::ICON_REBUILD);
    rebuildIcon.addFile(ProjectExplorer::Constants::ICON_REBUILD_SMALL);
    m_rebuildSubProjectContextMenu = new QAction(rebuildIcon, tr("Rebuild"), this);
    command = am->registerAction(m_rebuildSubProjectContextMenu, Constants::REBUILDSUBDIR, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_rebuildSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(rebuildSubDirContextMenu()));

    QIcon cleanIcon(ProjectExplorer::Constants::ICON_CLEAN);
    cleanIcon.addFile(ProjectExplorer::Constants::ICON_CLEAN_SMALL);
    m_cleanSubProjectContextMenu = new QAction(cleanIcon, tr("Clean"), this);
    command = am->registerAction(m_cleanSubProjectContextMenu, Constants::CLEANSUBDIR, m_projectContext);
    command->setAttribute(Core::Command::CA_Hide);
    msubproject->addAction(command, ProjectExplorer::Constants::G_PROJECT_BUILD);
    connect(m_cleanSubProjectContextMenu, SIGNAL(triggered()), m_qt4ProjectManager, SLOT(cleanSubDirContextMenu()));

    connect(m_projectExplorer,
            SIGNAL(aboutToShowContextMenu(ProjectExplorer::Project*, ProjectExplorer::Node*)),
            this, SLOT(updateContextMenu(ProjectExplorer::Project*, ProjectExplorer::Node*)));

    connect(m_projectExplorer->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project *)),
            this, SLOT(buildStateChanged(ProjectExplorer::Project *)));
    connect(m_projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project *)),
            this, SLOT(currentProjectChanged()));

    Core::ActionContainer *contextMenu = am->createMenu(Qt4ProjectManager::Constants::M_CONTEXT);

    Core::Command *cmd;

    Core::Context proFileEditorContext = Core::Context(Qt4ProjectManager::Constants::C_PROFILEEDITOR);

    QAction *jumpToFile = new QAction(tr("Jump to File Under Cursor"), this);
    cmd = am->registerAction(jumpToFile,
        Constants::JUMP_TO_FILE, proFileEditorContext);
    cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
    connect(jumpToFile, SIGNAL(triggered()),
            this, SLOT(jumpToFile()));
    contextMenu->addAction(cmd);

    QAction *addLibrary = new QAction(tr("Add Library..."), this);
    cmd = am->registerAction(addLibrary,
        Constants::ADDLIBRARY, proFileEditorContext);
    connect(addLibrary, SIGNAL(triggered()),
            this, SLOT(addLibrary()));
    contextMenu->addAction(cmd);

    QAction *separator = new QAction(this);
    separator->setSeparator(true);
    contextMenu->addAction(am->registerAction(separator,
                  Core::Id(Constants::SEPARATOR), proFileEditorContext));

    cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
    contextMenu->addAction(cmd);

    return true;
}

void Qt4ProjectManagerPlugin::extensionsInitialized()
{
    m_qt4ProjectManager->init();
}

void Qt4ProjectManagerPlugin::updateContextMenu(Project *project,
                                                ProjectExplorer::Node *node)
{
    m_qt4ProjectManager->setContextProject(project);
    m_qt4ProjectManager->setContextNode(node);
    m_runQMakeActionContextMenu->setEnabled(false);
    m_buildSubProjectContextMenu->setEnabled(false);
    m_rebuildSubProjectContextMenu->setEnabled(false);
    m_cleanSubProjectContextMenu->setEnabled(false);

    Qt4ProFileNode *proFileNode = qobject_cast<Qt4ProFileNode *>(node);
    if (qobject_cast<Qt4Project *>(project) && proFileNode) {
        m_runQMakeActionContextMenu->setVisible(true);
        m_buildSubProjectContextMenu->setVisible(true);
        m_rebuildSubProjectContextMenu->setVisible(true);
        m_cleanSubProjectContextMenu->setVisible(true);

        if (!m_projectExplorer->buildManager()->isBuilding(project)) {
            m_runQMakeActionContextMenu->setEnabled(true);
            m_buildSubProjectContextMenu->setEnabled(true);
            m_rebuildSubProjectContextMenu->setEnabled(true);
            m_cleanSubProjectContextMenu->setEnabled(true);
        }
    } else {
        m_runQMakeActionContextMenu->setVisible(false);
        m_buildSubProjectContextMenu->setVisible(false);
        m_rebuildSubProjectContextMenu->setVisible(false);
        m_cleanSubProjectContextMenu->setVisible(false);
    }
}

void Qt4ProjectManagerPlugin::currentProjectChanged()
{
    m_runQMakeAction->setEnabled(!m_projectExplorer->buildManager()->isBuilding(m_projectExplorer->currentProject()));
}

void Qt4ProjectManagerPlugin::buildStateChanged(ProjectExplorer::Project *pro)
{
    ProjectExplorer::Project *currentProject = m_projectExplorer->currentProject();
    if (pro == currentProject)
        m_runQMakeAction->setEnabled(!m_projectExplorer->buildManager()->isBuilding(currentProject));
    if (pro == m_qt4ProjectManager->contextProject())
        m_runQMakeActionContextMenu->setEnabled(!m_projectExplorer->buildManager()->isBuilding(pro));
}

void Qt4ProjectManagerPlugin::addLibrary()
{
    Core::EditorManager *em = Core::EditorManager::instance();
    ProFileEditor *editor = qobject_cast<ProFileEditor*>(em->currentEditor()->widget());
    if (editor)
        editor->addLibrary();
}

void Qt4ProjectManagerPlugin::jumpToFile()
{
    Core::EditorManager *em = Core::EditorManager::instance();
    ProFileEditor *editor = qobject_cast<ProFileEditor*>(em->currentEditor()->widget());
    if (editor)
        editor->jumpToFile();
}

#ifdef WITH_TESTS
void Qt4ProjectManagerPlugin::testBasicProjectLoading()
{
    QString testDirectory = ExtensionSystem::PluginManager::instance()->testDataDirectory() + "/qt4projectmanager/";
    QString test1 = testDirectory + "test1/test1.pro";
    m_projectExplorer->openProject(test1);
    QVERIFY(!m_projectExplorer->session()->projects().isEmpty());
    Qt4Project *qt4project = qobject_cast<Qt4Project *>(m_projectExplorer->session()->projects().first());
    QVERIFY(qt4project);
    QVERIFY(qt4project->rootProjectNode()->projectType() == ApplicationTemplate);
    QVERIFY(m_projectExplorer->currentProject() != 0);
}
#endif

Q_EXPORT_PLUGIN(Qt4ProjectManagerPlugin)
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "targetsetuppage.h"

#include "qt4project.h"
#include "qt4projectmanagerconstants.h"
#include "qt4target.h"

#include <utils/pathchooser.h>

#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLayout>
#include <QtGui/QTreeWidget>

using namespace Qt4ProjectManager::Internal;

TargetSetupPage::TargetSetupPage(QWidget *parent) :
    QWizardPage(parent),
    m_preferMobile(false)
{
    resize(500, 400);
    setTitle(tr("Set up targets for your project"));

    QVBoxLayout *vbox = new QVBoxLayout(this);

    QLabel * importLabel = new QLabel(this);
    importLabel->setText(tr("Qt Creator can set up the following targets:"));
    importLabel->setWordWrap(true);

    vbox->addWidget(importLabel);

    m_treeWidget = new QTreeWidget(this);
    m_treeWidget->setColumnCount(3);
    m_treeWidget->header()->setResizeMode(0, QHeaderView::ResizeToContents);
    m_treeWidget->header()->setResizeMode(1, QHeaderView::ResizeToContents);
    m_treeWidget->setHeaderLabels(QStringList() << tr("Qt Version") << tr("Status") << tr("Directory"));
    vbox->addWidget(m_treeWidget);

    QHBoxLayout *hbox = new QHBoxLayout;
    m_directoryLabel = new QLabel(this);
    m_directoryLabel->setText(tr("Scan for builds"));
    hbox->addWidget(m_directoryLabel);

    m_directoryChooser = new Utils::PathChooser(this);
    m_directoryChooser->setPromptDialogTitle(tr("Directory to import builds from"));
    m_directoryChooser->setExpectedKind(Utils::PathChooser::Directory);
    hbox->addWidget(m_directoryChooser);
    vbox->addLayout(hbox);

    connect(m_directoryChooser, SIGNAL(changed(QString)),
            this, SLOT(importDirectoryAdded(QString)));
}

TargetSetupPage::~TargetSetupPage()
{
    resetInfos();
}

void TargetSetupPage::setImportInfos(const QList<ImportInfo> &infos)
{
    disconnect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
               this, SLOT(itemWasChanged()));

    // Clean up!
    resetInfos();

    // Find possible targets:
    QStringList targets;
    foreach (const ImportInfo &i, infos) {
        // Make sure we have no duplicate directories/version pairs:
        bool skip = false;
        foreach (const ImportInfo &j, m_infos) {
            if ((j.directory == i.directory) &&
                (j.version == i.version)) {
                skip = true;
                break;
            }
        }
        if (skip)
            continue;

        m_infos.append(i);

        QSet<QString> versionTargets = i.version->supportedTargetIds();
        foreach (const QString &t, versionTargets) {
            if (!targets.contains(t))
                targets.append(t);
        }
    }
    qSort(targets.begin(), targets.end());

    Qt4TargetFactory factory;
    foreach (const QString &t, targets) {
        QTreeWidgetItem *targetItem = new QTreeWidgetItem(m_treeWidget);
        targetItem->setText(0, factory.displayNameForId(t));
        targetItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        targetItem->setData(0, Qt::UserRole, t);
        targetItem->setExpanded(true);

        int pos = -1;
        foreach (const ImportInfo &i, infos) {
            ++pos;

            if (!i.version->supportsTargetId(t))
                continue;
            QTreeWidgetItem *versionItem = new QTreeWidgetItem(targetItem);
            // Column 0:
            versionItem->setText(0, i.version->displayName());
            versionItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            versionItem->setData(0, Qt::UserRole, pos);
            // Prefer imports to creating new builds, but precheck any
            // Qt that exists (if there is no import with that version)
            bool shouldCheck = true;
            if (!i.isExistingBuild) {
                foreach (const ImportInfo &j, m_infos) {
                    if (j.isExistingBuild && j.version == i.version) {
                        shouldCheck = false;
                        break;
                    }
                }
            }
            shouldCheck = shouldCheck && (m_preferMobile == i.version->supportsMobileTarget());
            shouldCheck = shouldCheck || i.isExistingBuild; // always check imports
            shouldCheck = shouldCheck || m_infos.count() == 1; // always check only option
            versionItem->setCheckState(0, shouldCheck ? Qt::Checked : Qt::Unchecked);

            // Column 1 (status):
            versionItem->setText(1, i.isExistingBuild ? tr("Import", "Is this an import of an existing build or a new one?") :
                                                        tr("New", "Is this an import of an existing build or a new one?"));

            // Column 2 (directory):
            versionItem->setText(2, QDir::toNativeSeparators(i.directory));
        }
    }

    connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
            this, SLOT(itemWasChanged()));

    emit completeChanged();
}

QList<TargetSetupPage::ImportInfo> TargetSetupPage::importInfos() const
{
    return m_infos;
}

bool TargetSetupPage::hasSelection() const
{
    for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
        QTreeWidgetItem * current = m_treeWidget->topLevelItem(i);
        for (int j = 0; j < current->childCount(); ++j) {
            QTreeWidgetItem * child = current->child(j);
            if (child->checkState(0) == Qt::Checked)
                return true;
        }
    }
    return false;
}

bool TargetSetupPage::isTargetSelected(const QString &targetid) const
{
    for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
        QTreeWidgetItem * current = m_treeWidget->topLevelItem(i);
        if (current->data(0, Qt::UserRole).toString() != targetid)
            continue;
        for (int j = 0; j < current->childCount(); ++j) {
            QTreeWidgetItem * child = current->child(j);
            if (child->checkState(0) == Qt::Checked)
                return true;
        }
    }
    return false;
}

bool TargetSetupPage::setupProject(Qt4ProjectManager::Qt4Project *project)
{
    Q_ASSERT(project->targets().isEmpty());

    for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
        QTreeWidgetItem *current = m_treeWidget->topLevelItem(i);
        QString targetId = current->data(0, Qt::UserRole).toString();

        QList<BuildConfigurationInfo> targetInfos;
        for (int j = 0; j < current->childCount(); ++j) {
            QTreeWidgetItem *child = current->child(j);
            if (child->checkState(0) != Qt::Checked)
                continue;

            const ImportInfo &info = m_infos.at(child->data(0, Qt::UserRole).toInt());

            if ((info.buildConfig | QtVersion::DebugBuild) != info.buildConfig)
                targetInfos.append(BuildConfigurationInfo(info.version, QtVersion::QmakeBuildConfigs(info.buildConfig | QtVersion::DebugBuild),
                                                          info.additionalArguments, info.directory));
            targetInfos.append(BuildConfigurationInfo(info.version, info.buildConfig,
                                                      info.additionalArguments, info.directory));
        }

        // create the target:
        Qt4Target *target = 0;
        if (!targetInfos.isEmpty())
            target = project->targetFactory()->create(project, targetId, targetInfos);

        if (target)
            project->addTarget(target);
    }

    // Create the default target if nothing else was set up:
    if (project->targets().isEmpty()) {
        Qt4Target *target = project->targetFactory()->create(project, Constants::DESKTOP_TARGET_ID);
        if (target)
            project->addTarget(target);
    }

    return !project->targets().isEmpty();
}

void TargetSetupPage::itemWasChanged()
{
    emit completeChanged();
}

bool TargetSetupPage::isComplete() const
{
    return hasSelection();
}

void TargetSetupPage::setImportDirectoryBrowsingEnabled(bool browsing)
{
    m_directoryChooser->setEnabled(browsing);
    m_directoryChooser->setVisible(browsing);
    m_directoryLabel->setVisible(browsing);
}

void TargetSetupPage::setImportDirectoryBrowsingLocation(const QString &directory)
{
    m_directoryChooser->setInitialBrowsePathBackup(directory);
}

void TargetSetupPage::setShowLocationInformation(bool location)
{
    m_treeWidget->setColumnCount(location ? 3 : 1);
}

void TargetSetupPage::setPreferMobile(bool mobile)
{
    m_preferMobile = mobile;
}

QList<TargetSetupPage::ImportInfo>
TargetSetupPage::importInfosForKnownQtVersions(Qt4ProjectManager::Qt4Project *project)
{
    QList<ImportInfo> results;
    QtVersionManager * vm = QtVersionManager::instance();
    QList<QtVersion *> validVersions = vm->validVersions();
    // Fallback in case no valid versions are found:
    if (validVersions.isEmpty())
        validVersions.append(vm->versions().at(0)); // there is always one!
    foreach (QtVersion *v, validVersions) {
        ImportInfo info;
        // ToDo: Check whether shadowbuilding is possible and use sourcedir if not:
        //       This needs a shadowbuilding patch to land
        if (project)
            info.directory = project->defaultTopLevelBuildDirectory();
        info.isExistingBuild = false;
        info.isTemporary = false;
        info.version = v;
        results.append(info);
    }
    return results;
}

QList<TargetSetupPage::ImportInfo> TargetSetupPage::filterImportInfos(const QSet<QString> &validTargets,
                                                                      const QList<ImportInfo> &infos)
{
    QList<ImportInfo> results;
    foreach (const ImportInfo &info, infos) {
        Q_ASSERT(info.version);
        foreach (const QString &target, validTargets) {
            if (info.version->supportsTargetId(target))
                results.append(info);
        }
    }
    return results;
}

QList<TargetSetupPage::ImportInfo>
TargetSetupPage::recursivelyCheckDirectoryForBuild(const QString &directory, int maxdepth)
{
    QList<ImportInfo> results;

    if (maxdepth <= 0)
        return results;

    // Check for in-source builds first:
    QString qmakeBinary =  QtVersionManager::findQMakeBinaryFromMakefile(directory);

    // Recurse into subdirectories:
    if (qmakeBinary.isNull()) {
        QStringList subDirs = QDir(directory).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
        foreach (QString subDir, subDirs)
            results.append(recursivelyCheckDirectoryForBuild(directory + QChar('/') + subDir, maxdepth - 1));
        return results;
    }

    // Shiny fresh directory with a Makefile...
    QtVersionManager * vm = QtVersionManager::instance();
    TargetSetupPage::ImportInfo info;
    info.directory = directory;

    // This also means we have a build in there
    // First get the qt version
    info.version = vm->qtVersionForQMakeBinary(qmakeBinary);
    info.isExistingBuild = true;

    // Okay does not yet exist, create
    if (!info.version) {
        info.version = new QtVersion(qmakeBinary);
        info.isTemporary = true;
    }

    QPair<QtVersion::QmakeBuildConfigs, QStringList> result =
            QtVersionManager::scanMakeFile(directory, info.version->defaultBuildConfig());
    info.buildConfig = result.first;
    info.additionalArguments = Qt4BuildConfiguration::removeSpecFromArgumentList(result.second);

    QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArgumentList(result.second, directory, info.version);
    QString versionSpec = info.version->mkspec();

    // Compare mkspecs and add to additional arguments
    if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") {
        // using the default spec, don't modify additional arguments
    } else {
        info.additionalArguments.prepend(parsedSpec);
        info.additionalArguments.prepend("-spec");
    }

    results.append(info);
    return results;
}

void TargetSetupPage::importDirectoryAdded(const QString &directory)
{
    QFileInfo dir(directory);
    if (!dir.exists() || !dir.isDir())
        return;
    m_directoryChooser->setPath(QString());
    QList<ImportInfo> tmp = m_infos;
    tmp.append(recursivelyCheckDirectoryForBuild(directory));
    setImportInfos(tmp);
}

void TargetSetupPage::resetInfos()
{
    m_treeWidget->clear();
    foreach (const ImportInfo &info, m_infos) {
        if (info.isTemporary)
            delete info.version;
    }
    m_infos.clear();
}
<commit_msg>Use shadowbuilding information from Qt versions<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "targetsetuppage.h"

#include "qt4project.h"
#include "qt4projectmanagerconstants.h"
#include "qt4target.h"

#include <utils/pathchooser.h>

#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLayout>
#include <QtGui/QTreeWidget>

using namespace Qt4ProjectManager::Internal;

TargetSetupPage::TargetSetupPage(QWidget *parent) :
    QWizardPage(parent),
    m_preferMobile(false)
{
    resize(500, 400);
    setTitle(tr("Set up targets for your project"));

    QVBoxLayout *vbox = new QVBoxLayout(this);

    QLabel * importLabel = new QLabel(this);
    importLabel->setText(tr("Qt Creator can set up the following targets:"));
    importLabel->setWordWrap(true);

    vbox->addWidget(importLabel);

    m_treeWidget = new QTreeWidget(this);
    m_treeWidget->setColumnCount(3);
    m_treeWidget->header()->setResizeMode(0, QHeaderView::ResizeToContents);
    m_treeWidget->header()->setResizeMode(1, QHeaderView::ResizeToContents);
    m_treeWidget->setHeaderLabels(QStringList() << tr("Qt Version") << tr("Status") << tr("Directory"));
    vbox->addWidget(m_treeWidget);

    QHBoxLayout *hbox = new QHBoxLayout;
    m_directoryLabel = new QLabel(this);
    m_directoryLabel->setText(tr("Scan for builds"));
    hbox->addWidget(m_directoryLabel);

    m_directoryChooser = new Utils::PathChooser(this);
    m_directoryChooser->setPromptDialogTitle(tr("Directory to import builds from"));
    m_directoryChooser->setExpectedKind(Utils::PathChooser::Directory);
    hbox->addWidget(m_directoryChooser);
    vbox->addLayout(hbox);

    connect(m_directoryChooser, SIGNAL(changed(QString)),
            this, SLOT(importDirectoryAdded(QString)));
}

TargetSetupPage::~TargetSetupPage()
{
    resetInfos();
}

void TargetSetupPage::setImportInfos(const QList<ImportInfo> &infos)
{
    disconnect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
               this, SLOT(itemWasChanged()));

    // Clean up!
    resetInfos();

    // Find possible targets:
    QStringList targets;
    foreach (const ImportInfo &i, infos) {
        // Make sure we have no duplicate directories/version pairs:
        bool skip = false;
        foreach (const ImportInfo &j, m_infos) {
            if ((j.directory == i.directory) &&
                (j.version == i.version)) {
                skip = true;
                break;
            }
        }
        if (skip)
            continue;

        m_infos.append(i);

        QSet<QString> versionTargets = i.version->supportedTargetIds();
        foreach (const QString &t, versionTargets) {
            if (!targets.contains(t))
                targets.append(t);
        }
    }
    qSort(targets.begin(), targets.end());

    Qt4TargetFactory factory;
    foreach (const QString &t, targets) {
        QTreeWidgetItem *targetItem = new QTreeWidgetItem(m_treeWidget);
        targetItem->setText(0, factory.displayNameForId(t));
        targetItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        targetItem->setData(0, Qt::UserRole, t);
        targetItem->setExpanded(true);

        int pos = -1;
        foreach (const ImportInfo &i, infos) {
            ++pos;

            if (!i.version->supportsTargetId(t))
                continue;
            QTreeWidgetItem *versionItem = new QTreeWidgetItem(targetItem);
            // Column 0:
            versionItem->setText(0, i.version->displayName());
            versionItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            versionItem->setData(0, Qt::UserRole, pos);
            // Prefer imports to creating new builds, but precheck any
            // Qt that exists (if there is no import with that version)
            bool shouldCheck = true;
            if (!i.isExistingBuild) {
                foreach (const ImportInfo &j, m_infos) {
                    if (j.isExistingBuild && j.version == i.version) {
                        shouldCheck = false;
                        break;
                    }
                }
            }
            shouldCheck = shouldCheck && (m_preferMobile == i.version->supportsMobileTarget());
            shouldCheck = shouldCheck || i.isExistingBuild; // always check imports
            shouldCheck = shouldCheck || m_infos.count() == 1; // always check only option
            versionItem->setCheckState(0, shouldCheck ? Qt::Checked : Qt::Unchecked);

            // Column 1 (status):
            versionItem->setText(1, i.isExistingBuild ? tr("Import", "Is this an import of an existing build or a new one?") :
                                                        tr("New", "Is this an import of an existing build or a new one?"));

            // Column 2 (directory):
            versionItem->setText(2, QDir::toNativeSeparators(i.directory));
        }
    }

    connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
            this, SLOT(itemWasChanged()));

    emit completeChanged();
}

QList<TargetSetupPage::ImportInfo> TargetSetupPage::importInfos() const
{
    return m_infos;
}

bool TargetSetupPage::hasSelection() const
{
    for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
        QTreeWidgetItem * current = m_treeWidget->topLevelItem(i);
        for (int j = 0; j < current->childCount(); ++j) {
            QTreeWidgetItem * child = current->child(j);
            if (child->checkState(0) == Qt::Checked)
                return true;
        }
    }
    return false;
}

bool TargetSetupPage::isTargetSelected(const QString &targetid) const
{
    for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
        QTreeWidgetItem * current = m_treeWidget->topLevelItem(i);
        if (current->data(0, Qt::UserRole).toString() != targetid)
            continue;
        for (int j = 0; j < current->childCount(); ++j) {
            QTreeWidgetItem * child = current->child(j);
            if (child->checkState(0) == Qt::Checked)
                return true;
        }
    }
    return false;
}

bool TargetSetupPage::setupProject(Qt4ProjectManager::Qt4Project *project)
{
    Q_ASSERT(project->targets().isEmpty());

    for (int i = 0; i < m_treeWidget->topLevelItemCount(); ++i) {
        QTreeWidgetItem *current = m_treeWidget->topLevelItem(i);
        QString targetId = current->data(0, Qt::UserRole).toString();

        QList<BuildConfigurationInfo> targetInfos;
        for (int j = 0; j < current->childCount(); ++j) {
            QTreeWidgetItem *child = current->child(j);
            if (child->checkState(0) != Qt::Checked)
                continue;

            const ImportInfo &info = m_infos.at(child->data(0, Qt::UserRole).toInt());

            if ((info.buildConfig | QtVersion::DebugBuild) != info.buildConfig)
                targetInfos.append(BuildConfigurationInfo(info.version, QtVersion::QmakeBuildConfigs(info.buildConfig | QtVersion::DebugBuild),
                                                          info.additionalArguments, info.directory));
            targetInfos.append(BuildConfigurationInfo(info.version, info.buildConfig,
                                                      info.additionalArguments, info.directory));
        }

        // create the target:
        Qt4Target *target = 0;
        if (!targetInfos.isEmpty())
            target = project->targetFactory()->create(project, targetId, targetInfos);

        if (target)
            project->addTarget(target);
    }

    // Create the default target if nothing else was set up:
    if (project->targets().isEmpty()) {
        Qt4Target *target = project->targetFactory()->create(project, Constants::DESKTOP_TARGET_ID);
        if (target)
            project->addTarget(target);
    }

    return !project->targets().isEmpty();
}

void TargetSetupPage::itemWasChanged()
{
    emit completeChanged();
}

bool TargetSetupPage::isComplete() const
{
    return hasSelection();
}

void TargetSetupPage::setImportDirectoryBrowsingEnabled(bool browsing)
{
    m_directoryChooser->setEnabled(browsing);
    m_directoryChooser->setVisible(browsing);
    m_directoryLabel->setVisible(browsing);
}

void TargetSetupPage::setImportDirectoryBrowsingLocation(const QString &directory)
{
    m_directoryChooser->setInitialBrowsePathBackup(directory);
}

void TargetSetupPage::setShowLocationInformation(bool location)
{
    m_treeWidget->setColumnCount(location ? 3 : 1);
}

void TargetSetupPage::setPreferMobile(bool mobile)
{
    m_preferMobile = mobile;
}

QList<TargetSetupPage::ImportInfo>
TargetSetupPage::importInfosForKnownQtVersions(Qt4ProjectManager::Qt4Project *project)
{
    QList<ImportInfo> results;
    QtVersionManager * vm = QtVersionManager::instance();
    QList<QtVersion *> validVersions = vm->validVersions();
    // Fallback in case no valid versions are found:
    if (validVersions.isEmpty())
        validVersions.append(vm->versions().at(0)); // there is always one!
    foreach (QtVersion *v, validVersions) {
        ImportInfo info;
        if (project) {
            if (v->supportsShadowBuilds())
                info.directory = project->defaultTopLevelBuildDirectory();
            else
                info.directory = project->projectDirectory();
        }
        info.isExistingBuild = false;
        info.isTemporary = false;
        info.version = v;
        results.append(info);
    }
    return results;
}

QList<TargetSetupPage::ImportInfo> TargetSetupPage::filterImportInfos(const QSet<QString> &validTargets,
                                                                      const QList<ImportInfo> &infos)
{
    QList<ImportInfo> results;
    foreach (const ImportInfo &info, infos) {
        Q_ASSERT(info.version);
        foreach (const QString &target, validTargets) {
            if (info.version->supportsTargetId(target))
                results.append(info);
        }
    }
    return results;
}

QList<TargetSetupPage::ImportInfo>
TargetSetupPage::recursivelyCheckDirectoryForBuild(const QString &directory, int maxdepth)
{
    QList<ImportInfo> results;

    if (maxdepth <= 0)
        return results;

    // Check for in-source builds first:
    QString qmakeBinary =  QtVersionManager::findQMakeBinaryFromMakefile(directory);

    // Recurse into subdirectories:
    if (qmakeBinary.isNull()) {
        QStringList subDirs = QDir(directory).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
        foreach (QString subDir, subDirs)
            results.append(recursivelyCheckDirectoryForBuild(directory + QChar('/') + subDir, maxdepth - 1));
        return results;
    }

    // Shiny fresh directory with a Makefile...
    QtVersionManager * vm = QtVersionManager::instance();
    TargetSetupPage::ImportInfo info;
    info.directory = directory;

    // This also means we have a build in there
    // First get the qt version
    info.version = vm->qtVersionForQMakeBinary(qmakeBinary);
    info.isExistingBuild = true;

    // Okay does not yet exist, create
    if (!info.version) {
        info.version = new QtVersion(qmakeBinary);
        info.isTemporary = true;
    }

    QPair<QtVersion::QmakeBuildConfigs, QStringList> result =
            QtVersionManager::scanMakeFile(directory, info.version->defaultBuildConfig());
    info.buildConfig = result.first;
    info.additionalArguments = Qt4BuildConfiguration::removeSpecFromArgumentList(result.second);

    QString parsedSpec = Qt4BuildConfiguration::extractSpecFromArgumentList(result.second, directory, info.version);
    QString versionSpec = info.version->mkspec();

    // Compare mkspecs and add to additional arguments
    if (parsedSpec.isEmpty() || parsedSpec == versionSpec || parsedSpec == "default") {
        // using the default spec, don't modify additional arguments
    } else {
        info.additionalArguments.prepend(parsedSpec);
        info.additionalArguments.prepend("-spec");
    }

    results.append(info);
    return results;
}

void TargetSetupPage::importDirectoryAdded(const QString &directory)
{
    QFileInfo dir(directory);
    if (!dir.exists() || !dir.isDir())
        return;
    m_directoryChooser->setPath(QString());
    QList<ImportInfo> tmp = m_infos;
    tmp.append(recursivelyCheckDirectoryForBuild(directory));
    setImportInfos(tmp);
}

void TargetSetupPage::resetInfos()
{
    m_treeWidget->clear();
    foreach (const ImportInfo &info, m_infos) {
        if (info.isTemporary)
            delete info.version;
    }
    m_infos.clear();
}
<|endoftext|>


<commit_before>/*
 * Spatial Computation - Manifestation of Spatial computing.
 * Copyright © 2014 Pranav Kant
 *
 * This code is available to you under Apache License Version 2.0, January
 * 2014. You can grab a copy of license from the same repository from where you
 * fetched this code.
 */

#include "llvm/ADT/DenseMap.h"
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/InstIterator.h"

#include "waves.h"

using namespace llvm;

void printInstructionsWithWaveNo(Function &F, WaveScalar &obj){
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I!=E; ++I){
    Instruction *instr = &*I;
    std::string str;
    raw_string_ostream rso(str);
    instr->print(rso);

    outs() << *instr << " -> " << obj.getWaveNo(str) << "\n";
  }
}

void printDefs(Instruction *instr){
  outs() << "Use :" << *instr << "\n";
  for (User::op_iterator it = instr->op_begin(), e = instr->op_end(); it!=e; it++){
    Instruction *vi = dyn_cast<Instruction>(*it);
    outs() << "\t\t" << *vi << "\n";
  }
}

void printUses(Instruction *instr){
  outs() << "Def :" << *instr << "\n";
  for (Value::use_iterator i = instr->use_begin(), ie = instr->use_end(); i != ie; i++){
    Instruction *vi = dyn_cast<Instruction>(*i);
    outs() << "\t\t" <<*vi << "\n";
  }
}

/*
  DataFlowGraph is a pass that would output the Data flow graph for
  corresponding function in DOT format.
*/
struct DataFlowGraph : public FunctionPass,
                       public SmallVectorImpl <std::pair<const BasicBlock*, const BasicBlock*> > {
  static char ID;
  DataFlowGraph() : FunctionPass(ID), SmallVectorImpl(10){}

  bool runOnFunction(Function &F) {
    if (F.getName() == "main")
      return false;

    SmallVectorImpl<std::pair<const BasicBlock*, const BasicBlock*> > *res = this;
    WaveScalar obj;
    obj.annotateWaves(F, res);
    outs() << "Outputting CFG Only ...\n";
    F.viewCFGOnly();
    outs() << "Outputting CFG ...\n";
    F.viewCFG();

    printInstructionsWithWaveNo(F, obj);

    outs() << "strict diGraph G{\n";
    std::vector<Instruction*> worklist;
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I!=E; ++I){
      Instruction *instr = &*I;
      worklist.push_back(instr);
    }

    for (std::vector<Instruction*>::iterator iter = worklist.begin();
         iter != worklist.end();
         iter++){
      Instruction *instr = *iter;
      printUses(instr);
    }
    /*
    for (std::vector<Instruction*>::iterator iter = worklist.begin(); iter != worklist.end(); iter++){
      Instruction *instr = *iter;
        std::string ppstr;
        raw_string_ostream rso1(ppstr);
        instr->print(rso1);
        std::string pstr = EscapeString(ppstr);

        for (Value::use_iterator i = instr->use_begin(), ie = instr->use_end(); i != ie; i++){
          Value *v = *i;
          Instruction *vi = dyn_cast<Instruction>(v);
          std::string str;
          raw_string_ostream rso(str);
          vi->print(rso);
          std::string istr = EscapeString(str);

          if (!obj.isSameWave(instr, vi))
            outs() << "\"" <<pstr << "\"" << WA() << "\"" <<istr << "\";\n";
          else
            outs() << "\"" << pstr << "\" -> \"" << istr << "\";\n";
        }
    }

    for (std::vector<Instruction*>::iterator iter = worklist.begin(); iter!=worklist.end(); iter++){
      Instruction *instr = *iter;
        std::string ppstr;
        raw_string_ostream rso1(ppstr);
        instr->print(rso1);
        std::string pstr = EscapeString(ppstr);

      for (User::op_iterator it = instr->op_begin(), e = instr->op_end(); it!=e; it++){
        Value *v = *it;
        Instruction *vi = dyn_cast<Instruction>(*it);

        std::string str;
        raw_string_ostream rso(str);
        vi->print(rso);
        std::string istr = EscapeString(str);
        if (istr.compare("")==0 or pstr.compare("")==0)
          continue;

        if (!obj.isSameWave(instr, vi))
          outs() << "\"" << pstr << "\"" << WA() << "\"" << istr << "\";\n";
        else
          outs() << "\"" << istr << "\" -> \"" << pstr << "\";\n";
      }
    }
    outs() << "}";
    */
    return false;
  }
};

char DataFlowGraph::ID = 0;
static RegisterPass<DataFlowGraph> X("dot-dataflow",
                                     "Output Dataflow Graph in DOT format for WaveScalar Architecture",
                                     false, false);
<commit_msg>Added a working pass using GraphTraits and DOTGraphTraits<commit_after>/*
 * Spatial Computation - Manifestation of Spatial computing.
 * Copyright © 2014 Pranav Kant
 *
 * This code is available to you under Apache License Version 2.0, January
 * 2014. You can grab a copy of license from the same repository from where you
 * fetched this code.
 */

#include "llvm/ADT/DenseMap.h"
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/DataFlow.h"
#include "llvm/Support/GraphWriter.h"

#include "waves.h"

using namespace llvm;

void printInstructionsWithWaveNo(Function &F, WaveScalar &obj){
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I!=E; ++I){
    Instruction *instr = &*I;
    std::string str;
    raw_string_ostream rso(str);
    instr->print(rso);

    outs() << *instr << " -> " << obj.getWaveNo(str) << "\n";
  }
}

void printDefs(Instruction *instr){
  outs() << "Use :" << *instr << "\n";
  for (User::op_iterator it = instr->op_begin(), e = instr->op_end(); it!=e; it++){
    Instruction *vi = dyn_cast<Instruction>(*it);
    outs() << "\t\t" << *vi << "\n";
  }
}

void printUses(Instruction *instr){
  outs() << "Def :" << *instr << "\n";
  for (Value::use_iterator i = instr->use_begin(), ie = instr->use_end(); i != ie; i++){
    Instruction *vi = dyn_cast<Instruction>(*i);
    outs() << "\t\t" <<*vi << "\n";
  }
}

template<typename T>
class DFG{
  T p;
public:
  DFG(T t) : p(t) { }
  T operator*() {return p;}
};

template<>
struct DOTGraphTraits<DFG<Function*> > : public DefaultDOTGraphTraits{
  explicit DOTGraphTraits(bool isSimple=false) : DefaultDOTGraphTraits(isSimple){}

  static std::string getGraphName(DFG<Function*> F){
    return "DFG for function";
  }

  static std::string getNodeLabel(Value *v, const DFG<Function*> &F){
    Instruction *instr = dyn_cast<Instruction>(v);
    std::string str;
    raw_string_ostream rso(str);
    instr->print(rso);

    return str;
  }
};

template<>
struct GraphTraits<DFG<Function*> > : public GraphTraits<Value*> {
  typedef inst_iterator nodes_iterator;

  static nodes_iterator nodes_begin(DFG<Function*> F){
    return inst_begin(*F);
  }

  static nodes_iterator nodes_end(DFG<Function*> F){
    return inst_end(*F);
  }
};

/*
  DataFlowGraph is a pass that would output the Data flow graph for
  corresponding function in DOT format.
*/
struct DataFlowGraph : public FunctionPass,
                       public SmallVectorImpl <std::pair<const BasicBlock*, const BasicBlock*> > {
  static char ID;
  DataFlowGraph() : FunctionPass(ID), SmallVectorImpl(10){}

  bool runOnFunction(Function &F) {
    if (F.getName() == "main")
      return false;

    SmallVectorImpl<std::pair<const BasicBlock*, const BasicBlock*> > *res = this;
    WaveScalar obj;
    obj.annotateWaves(F, res);
    outs() << "Outputting CFG Only ...\n";
    F.viewCFGOnly();
    outs() << "Outputting CFG ...\n";
    F.viewCFG();

    printInstructionsWithWaveNo(F, obj);

    outs() << "strict diGraph G{\n";
    std::vector<Instruction*> worklist;
    for (inst_iterator I = inst_begin(F), E = inst_end(F); I!=E; ++I){
      Instruction *instr = &*I;
      worklist.push_back(instr);
    }

    for (std::vector<Instruction*>::iterator iter = worklist.begin();
         iter != worklist.end();
         iter++){
      Instruction *instr = *iter;
      printUses(instr);
    }

    //    GraphWriter<DFG<Function*> > g(F);
    std::string ErrorInfo;
    raw_fd_ostream File("dfg.dot", ErrorInfo);
    WriteGraph (File, (DFG<Function*>)&F);

    /*
    for (std::vector<Instruction*>::iterator iter = worklist.begin(); iter != worklist.end(); iter++){
      Instruction *instr = *iter;
        std::string ppstr;
        raw_string_ostream rso1(ppstr);
        instr->print(rso1);
        std::string pstr = EscapeString(ppstr);

        for (Value::use_iterator i = instr->use_begin(), ie = instr->use_end(); i != ie; i++){
          Value *v = *i;
          Instruction *vi = dyn_cast<Instruction>(v);
          std::string str;
          raw_string_ostream rso(str);
          vi->print(rso);
          std::string istr = EscapeString(str);

          if (!obj.isSameWave(instr, vi))
            outs() << "\"" <<pstr << "\"" << WA() << "\"" <<istr << "\";\n";
          else
            outs() << "\"" << pstr << "\" -> \"" << istr << "\";\n";
        }
    }

    for (std::vector<Instruction*>::iterator iter = worklist.begin(); iter!=worklist.end(); iter++){
      Instruction *instr = *iter;
        std::string ppstr;
        raw_string_ostream rso1(ppstr);
        instr->print(rso1);
        std::string pstr = EscapeString(ppstr);

      for (User::op_iterator it = instr->op_begin(), e = instr->op_end(); it!=e; it++){
        Value *v = *it;
        Instruction *vi = dyn_cast<Instruction>(*it);

        std::string str;
        raw_string_ostream rso(str);
        vi->print(rso);
        std::string istr = EscapeString(str);
        if (istr.compare("")==0 or pstr.compare("")==0)
          continue;

        if (!obj.isSameWave(instr, vi))
          outs() << "\"" << pstr << "\"" << WA() << "\"" << istr << "\";\n";
        else
          outs() << "\"" << istr << "\" -> \"" << pstr << "\";\n";
      }
    }
    outs() << "}";
    */
    return false;
  }
};

char DataFlowGraph::ID = 0;
static RegisterPass<DataFlowGraph> X("dot-dataflow",
                                     "Output Dataflow Graph in DOT format for WaveScalar Architecture",
                                     false, false);
<|endoftext|>