genericproject.cpp 18.5 KB
Newer Older
Roberto Raggi's avatar
Roberto Raggi committed
1 2 3 4
/**************************************************************************
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
Roberto Raggi's avatar
Roberto Raggi committed
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
Roberto Raggi's avatar
Roberto Raggi committed
8 9 10 11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
Roberto Raggi's avatar
Roberto Raggi committed
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.nokia.com.
Roberto Raggi's avatar
Roberto Raggi committed
30 31 32 33
**
**************************************************************************/

#include "genericproject.h"
Tobias Hunger's avatar
Tobias Hunger committed
34

dt's avatar
dt committed
35
#include "genericbuildconfiguration.h"
Tobias Hunger's avatar
Tobias Hunger committed
36 37
#include "genericprojectconstants.h"
#include "generictarget.h"
Roberto Raggi's avatar
Roberto Raggi committed
38

39
#include <projectexplorer/abi.h>
40
#include <projectexplorer/buildenvironmentwidget.h>
41
#include <projectexplorer/headerpath.h>
42
#include <projectexplorer/customexecutablerunconfiguration.h>
43
#include <projectexplorer/toolchainmanager.h>
Roberto Raggi's avatar
Roberto Raggi committed
44
#include <projectexplorer/projectexplorerconstants.h>
45
#include <cplusplus/ModelManagerInterface.h>
Roberto Raggi's avatar
Roberto Raggi committed
46
#include <extensionsystem/pluginmanager.h>
47
#include <utils/pathchooser.h>
hjk's avatar
hjk committed
48
#include <utils/qtcassert.h>
49
#include <utils/fileutils.h>
Roberto Raggi's avatar
Roberto Raggi committed
50
#include <coreplugin/icore.h>
51
#include <coreplugin/icontext.h>
Roberto Raggi's avatar
Roberto Raggi committed
52

53
#include <QtCore/QDir>
54
#include <QtCore/QProcessEnvironment>
Roberto Raggi's avatar
Roberto Raggi committed
55

56 57 58
#include <QtGui/QFormLayout>
#include <QtGui/QMainWindow>
#include <QtGui/QComboBox>
Roberto Raggi's avatar
Roberto Raggi committed
59 60 61

using namespace GenericProjectManager;
using namespace GenericProjectManager::Internal;
62
using namespace ProjectExplorer;
Roberto Raggi's avatar
Roberto Raggi committed
63

64
namespace {
65
const char * const TOOLCHAIN_KEY("GenericProjectManager.GenericProject.Toolchain");
66 67
} // end of anonymous namespace

68 69 70 71
////////////////////////////////////////////////////////////////////////////////////
// GenericProject
////////////////////////////////////////////////////////////////////////////////////

Roberto Raggi's avatar
Roberto Raggi committed
72
GenericProject::GenericProject(Manager *manager, const QString &fileName)
73 74 75
    : m_manager(manager),
      m_fileName(fileName),
      m_toolChain(0)
Roberto Raggi's avatar
Roberto Raggi committed
76
{
77 78 79
    setProjectContext(Core::Context(GenericProjectManager::Constants::PROJECTCONTEXT));
    setProjectLanguage(Core::Context(ProjectExplorer::Constants::LANG_CXX));

80
    QFileInfo fileInfo(m_fileName);
81 82
    QDir dir = fileInfo.dir();

83
    m_projectName      = fileInfo.completeBaseName();
84 85 86
    m_filesFileName    = QFileInfo(dir, m_projectName + QLatin1String(".files")).absoluteFilePath();
    m_includesFileName = QFileInfo(dir, m_projectName + QLatin1String(".includes")).absoluteFilePath();
    m_configFileName   = QFileInfo(dir, m_projectName + QLatin1String(".config")).absoluteFilePath();
87

88 89
    m_file = new GenericProjectFile(this, fileName);
    m_rootNode = new GenericProjectNode(this, m_file);
90

91
    m_manager->registerProject(this);
Roberto Raggi's avatar
Roberto Raggi committed
92 93 94 95
}

GenericProject::~GenericProject()
{
96
    m_codeModelFuture.cancel();
97
    m_manager->unregisterProject(this);
98

99
    delete m_rootNode;
100
    // do not delete m_toolChain
Roberto Raggi's avatar
Roberto Raggi committed
101 102
}

Tobias Hunger's avatar
Tobias Hunger committed
103
GenericTarget *GenericProject::activeTarget() const
104
{
Tobias Hunger's avatar
Tobias Hunger committed
105
    return static_cast<GenericTarget *>(Project::activeTarget());
106 107
}

108
QString GenericProject::filesFileName() const
hjk's avatar
hjk committed
109 110 111
{
    return m_filesFileName;
}
112 113

QString GenericProject::includesFileName() const
hjk's avatar
hjk committed
114 115 116
{
    return m_includesFileName;
}
117 118

QString GenericProject::configFileName() const
hjk's avatar
hjk committed
119 120 121
{
    return m_configFileName;
}
122

123
static QStringList readLines(const QString &absoluteFileName)
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
{
    QStringList lines;

    QFile file(absoluteFileName);
    if (file.open(QFile::ReadOnly)) {
        QTextStream stream(&file);

        forever {
            QString line = stream.readLine();
            if (line.isNull())
                break;

            lines.append(line);
        }
    }

    return lines;
}

143
bool GenericProject::saveRawFileList(const QStringList &rawFileList)
144
{
145
    // Make sure we can open the file for writing
146 147 148 149 150 151 152 153
    Utils::FileSaver saver(filesFileName(), QIODevice::Text);
    if (!saver.hasError()) {
        QTextStream stream(saver.file());
        foreach (const QString &filePath, rawFileList)
            stream << filePath << QLatin1Char('\n');
        saver.setResult(&stream);
    }
    if (!saver.finalize(Core::ICore::instance()->mainWindow()))
154 155 156
        return false;
    refresh(GenericProject::Files);
    return true;
157
}
158

159 160
bool GenericProject::addFiles(const QStringList &filePaths)
{
161 162 163 164 165
    QStringList newList = m_rawFileList;

    QDir baseDir(QFileInfo(m_fileName).dir());
    foreach (const QString &filePath, filePaths)
        newList.append(baseDir.relativeFilePath(filePath));
166

167
    return saveRawFileList(newList);
168 169 170 171
}

bool GenericProject::removeFiles(const QStringList &filePaths)
{
172
    QStringList newList = m_rawFileList;
173

174 175 176 177
    foreach (const QString &filePath, filePaths) {
        QHash<QString, QString>::iterator i = m_rawListEntries.find(filePath);
        if (i != m_rawListEntries.end())
            newList.removeOne(i.value());
178
    }
179

180
    return saveRawFileList(newList);
181 182
}

183 184 185 186 187 188 189 190 191 192
bool GenericProject::setFiles(const QStringList &filePaths)
{
    QStringList newList;
    QDir baseDir(QFileInfo(m_fileName).dir());
    foreach (const QString &filePath, filePaths)
        newList.append(baseDir.relativeFilePath(filePath));

    return saveRawFileList(newList);
}

193
void GenericProject::parseProject(RefreshOptions options)
Roberto Raggi's avatar
Roberto Raggi committed
194
{
195 196 197
    if (options & Files) {
        m_rawListEntries.clear();
        m_rawFileList = readLines(filesFileName());
198
        m_files = processEntries(m_rawFileList, &m_rawListEntries);
199
    }
200

201
    if (options & Configuration) {
202
        m_projectIncludePaths = processEntries(readLines(includesFileName()));
203

204 205
        // TODO: Possibly load some configuration from the project file
        //QSettings projectInfo(m_fileName, QSettings::IniFormat);
Roberto Raggi's avatar
Roberto Raggi committed
206

207
        m_defines.clear();
Roberto Raggi's avatar
Roberto Raggi committed
208

209 210 211 212
        QFile configFile(configFileName());
        if (configFile.open(QFile::ReadOnly))
            m_defines = configFile.readAll();
    }
213

214 215
    if (options & Files)
        emit fileListChanged();
Roberto Raggi's avatar
Roberto Raggi committed
216 217
}

218
void GenericProject::refresh(RefreshOptions options)
Roberto Raggi's avatar
Roberto Raggi committed
219
{
220 221 222
    QSet<QString> oldFileList;
    if (!(options & Configuration))
        oldFileList = m_files.toSet();
223

224 225 226 227
    parseProject(options);

    if (options & Files)
        m_rootNode->refresh();
Roberto Raggi's avatar
Roberto Raggi committed
228

229
    CPlusPlus::CppModelManagerInterface *modelManager =
230
        CPlusPlus::CppModelManagerInterface::instance();
Roberto Raggi's avatar
Roberto Raggi committed
231

232
    if (modelManager) {
233
        CPlusPlus::CppModelManagerInterface::ProjectInfo pinfo = modelManager->projectInfo(this);
Roberto Raggi's avatar
Roberto Raggi committed
234

235 236 237
        if (m_toolChain) {
            pinfo.defines = m_toolChain->predefinedMacros();
            pinfo.defines += '\n';
Roberto Raggi's avatar
Roberto Raggi committed
238

239 240 241 242 243 244
            foreach (const HeaderPath &headerPath, m_toolChain->systemHeaderPaths()) {
                if (headerPath.kind() == HeaderPath::FrameworkHeaderPath)
                    pinfo.frameworkPaths.append(headerPath.path());
                else
                    pinfo.includePaths.append(headerPath.path());
            }
Roberto Raggi's avatar
Roberto Raggi committed
245 246
        }

247 248
        pinfo.includePaths += allIncludePaths();
        pinfo.defines += m_defines;
Roberto Raggi's avatar
Roberto Raggi committed
249 250

        // ### add _defines.
Roberto Raggi's avatar
Roberto Raggi committed
251 252
        pinfo.sourceFiles = files();
        pinfo.sourceFiles += generated();
Roberto Raggi's avatar
Roberto Raggi committed
253

254 255 256 257 258
        QStringList filesToUpdate;

        if (options & Configuration) {
            filesToUpdate = pinfo.sourceFiles;
            filesToUpdate.append(QLatin1String("<configuration>")); // XXX don't hardcode configuration file name
259 260
            // Full update, if there's a code model update, cancel it
            m_codeModelFuture.cancel();
261 262 263 264 265 266
        } else if (options & Files) {
            // Only update files that got added to the list
            QSet<QString> newFileList = m_files.toSet();
            newFileList.subtract(oldFileList);
            filesToUpdate.append(newFileList.toList());
        }
267

Roberto Raggi's avatar
Roberto Raggi committed
268
        modelManager->updateProjectInfo(pinfo);
269
        m_codeModelFuture = modelManager->updateSourceFiles(filesToUpdate);
Roberto Raggi's avatar
Roberto Raggi committed
270 271 272
    }
}

273
/**
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
 * Expands environment variables in the given \a string when they are written
 * like $$(VARIABLE).
 */
static void expandEnvironmentVariables(const QProcessEnvironment &env, QString &string)
{
    const static QRegExp candidate(QLatin1String("\\$\\$\\((.+)\\)"));

    int index = candidate.indexIn(string);
    while (index != -1) {
        const QString value = env.value(candidate.cap(1));

        string.replace(index, candidate.matchedLength(), value);
        index += value.length();

        index = candidate.indexIn(string, index);
    }
}

/**
 * Expands environment variables and converts the path from relative to the
 * project to an absolute path.
 *
296
 * The \a map variable is an optional argument that will map the returned
297
 * absolute paths back to their original \a entries.
298
 */
299 300
QStringList GenericProject::processEntries(const QStringList &paths,
                                           QHash<QString, QString> *map) const
Roberto Raggi's avatar
Roberto Raggi committed
301
{
302
    const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
303
    const QDir projectDir(QFileInfo(m_fileName).dir());
304

Roberto Raggi's avatar
Roberto Raggi committed
305
    QStringList absolutePaths;
306
    foreach (const QString &path, paths) {
307 308
        QString trimmedPath = path.trimmed();
        if (trimmedPath.isEmpty())
309 310
            continue;

311 312 313
        expandEnvironmentVariables(env, trimmedPath);

        const QString absPath = QFileInfo(projectDir, trimmedPath).absoluteFilePath();
314 315
        absolutePaths.append(absPath);
        if (map)
316
            map->insert(absPath, trimmedPath);
Roberto Raggi's avatar
Roberto Raggi committed
317 318 319 320 321
    }
    absolutePaths.removeDuplicates();
    return absolutePaths;
}

Roberto Raggi's avatar
Roberto Raggi committed
322 323 324
QStringList GenericProject::allIncludePaths() const
{
    QStringList paths;
325 326
    paths += m_includePaths;
    paths += m_projectIncludePaths;
Roberto Raggi's avatar
Roberto Raggi committed
327 328 329 330 331
    paths.removeDuplicates();
    return paths;
}

QStringList GenericProject::projectIncludePaths() const
hjk's avatar
hjk committed
332 333 334
{
    return m_projectIncludePaths;
}
Roberto Raggi's avatar
Roberto Raggi committed
335

Roberto Raggi's avatar
Roberto Raggi committed
336
QStringList GenericProject::files() const
hjk's avatar
hjk committed
337 338 339
{
    return m_files;
}
Roberto Raggi's avatar
Roberto Raggi committed
340 341

QStringList GenericProject::generated() const
hjk's avatar
hjk committed
342 343 344
{
    return m_generated;
}
Roberto Raggi's avatar
Roberto Raggi committed
345 346

QStringList GenericProject::includePaths() const
hjk's avatar
hjk committed
347 348 349
{
    return m_includePaths;
}
Roberto Raggi's avatar
Roberto Raggi committed
350 351

void GenericProject::setIncludePaths(const QStringList &includePaths)
hjk's avatar
hjk committed
352 353 354
{
    m_includePaths = includePaths;
}
Roberto Raggi's avatar
Roberto Raggi committed
355

Roberto Raggi's avatar
Roberto Raggi committed
356
QByteArray GenericProject::defines() const
hjk's avatar
hjk committed
357 358 359
{
    return m_defines;
}
Roberto Raggi's avatar
Roberto Raggi committed
360

361
void GenericProject::setToolChain(ToolChain *tc)
Roberto Raggi's avatar
Roberto Raggi committed
362
{
363 364
    if (m_toolChain == tc)
        return;
Roberto Raggi's avatar
Roberto Raggi committed
365

366
    m_toolChain = tc;
367 368
    refresh(Configuration);

369 370 371 372 373
    foreach (Target *t, targets()) {
        foreach (BuildConfiguration *bc, t->buildConfigurations())
            bc->setToolChain(tc);
    }

374
    emit toolChainChanged(m_toolChain);
Roberto Raggi's avatar
Roberto Raggi committed
375 376
}

377
ToolChain *GenericProject::toolChain() const
378 379 380 381
{
    return m_toolChain;
}

382
QString GenericProject::displayName() const
Roberto Raggi's avatar
Roberto Raggi committed
383
{
384
    return m_projectName;
Roberto Raggi's avatar
Roberto Raggi committed
385 386
}

Tobias Hunger's avatar
Tobias Hunger committed
387 388
QString GenericProject::id() const
{
Tobias Hunger's avatar
Tobias Hunger committed
389
    return QLatin1String(Constants::GENERICPROJECT_ID);
Tobias Hunger's avatar
Tobias Hunger committed
390 391
}

Roberto Raggi's avatar
Roberto Raggi committed
392 393
Core::IFile *GenericProject::file() const
{
394
    return m_file;
Roberto Raggi's avatar
Roberto Raggi committed
395 396
}

397
IProjectManager *GenericProject::projectManager() const
Roberto Raggi's avatar
Roberto Raggi committed
398
{
399
    return m_manager;
Roberto Raggi's avatar
Roberto Raggi committed
400 401
}

402
QList<Project *> GenericProject::dependsOn()
Roberto Raggi's avatar
Roberto Raggi committed
403 404 405 406
{
    return QList<Project *>();
}

407
QList<BuildConfigWidget*> GenericProject::subConfigWidgets()
Roberto Raggi's avatar
Roberto Raggi committed
408
{
409
    QList<BuildConfigWidget*> list;
410 411
    list << new BuildEnvironmentWidget;
    return list;
Roberto Raggi's avatar
Roberto Raggi committed
412 413
}

414
GenericProjectNode *GenericProject::rootProjectNode() const
Roberto Raggi's avatar
Roberto Raggi committed
415
{
416
    return m_rootNode;
Roberto Raggi's avatar
Roberto Raggi committed
417 418 419 420
}

QStringList GenericProject::files(FilesMode fileMode) const
{
421
    Q_UNUSED(fileMode)
422
    return m_files; // ### TODO: handle generated files here.
Roberto Raggi's avatar
Roberto Raggi committed
423 424
}

Tobias Hunger's avatar
Tobias Hunger committed
425
QStringList GenericProject::buildTargets() const
Roberto Raggi's avatar
Roberto Raggi committed
426 427 428 429 430 431 432
{
    QStringList targets;
    targets.append(QLatin1String("all"));
    targets.append(QLatin1String("clean"));
    return targets;
}

433
QVariantMap GenericProject::toMap() const
Roberto Raggi's avatar
Roberto Raggi committed
434
{
435
    QVariantMap map(Project::toMap());
436
    map.insert(QLatin1String(TOOLCHAIN_KEY), m_toolChain ? m_toolChain->id() : QString());
437 438 439 440 441 442 443
    return map;
}

bool GenericProject::fromMap(const QVariantMap &map)
{
    if (!Project::fromMap(map))
        return false;
Roberto Raggi's avatar
Roberto Raggi committed
444

445 446 447 448 449 450 451 452 453
    // Sanity check: We need both a buildconfiguration and a runconfiguration!
    QList<Target *> targetList = targets();
    foreach (Target *t, targetList) {
        if (!t->activeBuildConfiguration()) {
            removeTarget(t);
            delete t;
            continue;
        }
        if (!t->activeRunConfiguration())
454
            t->addRunConfiguration(new CustomExecutableRunConfiguration(t));
455 456 457
    }

    // Add default setup:
458 459 460 461 462
    if (targets().isEmpty()) {
        GenericTargetFactory *factory =
                ExtensionSystem::PluginManager::instance()->getObject<GenericTargetFactory>();
        addTarget(factory->create(this, QLatin1String(GENERIC_DESKTOP_TARGET_ID)));
    }
463

464
    QString id = map.value(QLatin1String(TOOLCHAIN_KEY)).toString();
465 466
    const ToolChainManager *toolChainManager = ToolChainManager::instance();

467
    if (!id.isNull()) {
468
        setToolChain(toolChainManager->findToolChain(id));
469
    } else {
470 471 472 473
        ProjectExplorer::Abi abi = ProjectExplorer::Abi::hostAbi();
        abi = ProjectExplorer::Abi(abi.architecture(), abi.os(),  ProjectExplorer::Abi::UnknownFlavor,
                                   abi.binaryFormat(), abi.wordWidth() == 32 ? 32 : 0);
        QList<ToolChain *> tcs = toolChainManager->findToolChains(abi);
474
        if (tcs.isEmpty())
475
            tcs = toolChainManager->toolChains();
476 477 478
        if (!tcs.isEmpty())
            setToolChain(tcs.at(0));
    }
Roberto Raggi's avatar
Roberto Raggi committed
479 480

    setIncludePaths(allIncludePaths());
481

482
    refresh(Everything);
dt's avatar
dt committed
483
    return true;
484 485
}

Roberto Raggi's avatar
Roberto Raggi committed
486 487 488
////////////////////////////////////////////////////////////////////////////////////
// GenericBuildSettingsWidget
////////////////////////////////////////////////////////////////////////////////////
489

490
GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericTarget *target)
491
    : m_target(target), m_toolChainChooser(0), m_buildConfiguration(0)
Roberto Raggi's avatar
Roberto Raggi committed
492 493
{
    QFormLayout *fl = new QFormLayout(this);
494 495
    fl->setContentsMargins(0, -1, 0, -1);
    fl->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
496 497

    // build directory
498
    m_pathChooser = new Utils::PathChooser(this);
499
    m_pathChooser->setEnabled(true);
500
    m_pathChooser->setBaseDirectory(m_target->genericProject()->projectDirectory());
501
    fl->addRow(tr("Build directory:"), m_pathChooser);
con's avatar
con committed
502
    connect(m_pathChooser, SIGNAL(changed(QString)), this, SLOT(buildDirectoryChanged()));
503

504
    // tool chain
505 506 507 508 509 510 511 512
    m_toolChainChooser = new QComboBox;
    m_toolChainChooser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    updateToolChainList();

    fl->addRow(tr("Tool chain:"), m_toolChainChooser);
    connect(m_toolChainChooser, SIGNAL(activated(int)), this, SLOT(toolChainSelected(int)));
    connect(m_target->genericProject(), SIGNAL(toolChainChanged(ProjectExplorer::ToolChain*)),
            this, SLOT(toolChainChanged(ProjectExplorer::ToolChain*)));
513
    connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)),
514
            this, SLOT(updateToolChainList()));
515
    connect(ProjectExplorer::ToolChainManager::instance(), SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)),
516
            this, SLOT(updateToolChainList()));
Roberto Raggi's avatar
Roberto Raggi committed
517 518 519 520 521 522 523 524
}

GenericBuildSettingsWidget::~GenericBuildSettingsWidget()
{ }

QString GenericBuildSettingsWidget::displayName() const
{ return tr("Generic Manager"); }

dt's avatar
dt committed
525
void GenericBuildSettingsWidget::init(BuildConfiguration *bc)
Roberto Raggi's avatar
Roberto Raggi committed
526
{
527
    m_buildConfiguration = static_cast<GenericBuildConfiguration *>(bc);
528
    m_pathChooser->setPath(m_buildConfiguration->rawBuildDirectory());
Roberto Raggi's avatar
Roberto Raggi committed
529 530 531 532
}

void GenericBuildSettingsWidget::buildDirectoryChanged()
{
533
    m_buildConfiguration->setBuildDirectory(m_pathChooser->rawPath());
Roberto Raggi's avatar
Roberto Raggi committed
534 535
}

536 537 538 539
void GenericBuildSettingsWidget::toolChainSelected(int index)
{
    using namespace ProjectExplorer;

540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
    ToolChain *tc = static_cast<ToolChain *>(m_toolChainChooser->itemData(index).value<void *>());
    m_target->genericProject()->setToolChain(tc);
}

void GenericBuildSettingsWidget::toolChainChanged(ProjectExplorer::ToolChain *tc)
{
    for (int i = 0; i < m_toolChainChooser->count(); ++i) {
        ToolChain * currentTc = static_cast<ToolChain *>(m_toolChainChooser->itemData(i).value<void *>());
        if (currentTc != tc)
            continue;
        m_toolChainChooser->setCurrentIndex(i);
        return;
    }
}

void GenericBuildSettingsWidget::updateToolChainList()
{
    m_toolChainChooser->clear();

    QList<ToolChain *> tcs = ToolChainManager::instance()->toolChains();
    if (!m_target->genericProject()->toolChain()) {
561
        m_toolChainChooser->addItem(tr("<Invalid tool chain>"), qVariantFromValue(static_cast<void *>(0)));
562 563 564 565 566 567 568 569
        m_toolChainChooser->setCurrentIndex(0);
    }
    foreach (ToolChain *tc, tcs) {
        m_toolChainChooser->addItem(tc->displayName(), qVariantFromValue(static_cast<void *>(tc)));
        if (m_target->genericProject()->toolChain()
                && m_target->genericProject()->toolChain()->id() == tc->id())
            m_toolChainChooser->setCurrentIndex(m_toolChainChooser->count() - 1);
    }
570 571
}

Roberto Raggi's avatar
Roberto Raggi committed
572 573 574
////////////////////////////////////////////////////////////////////////////////////
// GenericProjectFile
////////////////////////////////////////////////////////////////////////////////////
575

Roberto Raggi's avatar
Roberto Raggi committed
576 577
GenericProjectFile::GenericProjectFile(GenericProject *parent, QString fileName)
    : Core::IFile(parent),
578 579
      m_project(parent),
      m_fileName(fileName)
Roberto Raggi's avatar
Roberto Raggi committed
580 581 582 583 584
{ }

GenericProjectFile::~GenericProjectFile()
{ }

585
bool GenericProjectFile::save(QString *, const QString &, bool)
Roberto Raggi's avatar
Roberto Raggi committed
586 587 588 589 590 591
{
    return false;
}

QString GenericProjectFile::fileName() const
{
592
    return m_fileName;
Roberto Raggi's avatar
Roberto Raggi committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624
}

QString GenericProjectFile::defaultPath() const
{
    return QString();
}

QString GenericProjectFile::suggestedFileName() const
{
    return QString();
}

QString GenericProjectFile::mimeType() const
{
    return Constants::GENERICMIMETYPE;
}

bool GenericProjectFile::isModified() const
{
    return false;
}

bool GenericProjectFile::isReadOnly() const
{
    return true;
}

bool GenericProjectFile::isSaveAsAllowed() const
{
    return false;
}

dt's avatar
dt committed
625 626 627 628
void GenericProjectFile::rename(const QString &newName)
{
    // Can't happen
    Q_UNUSED(newName);
629
    QTC_CHECK(false);
dt's avatar
dt committed
630 631
}

632
Core::IFile::ReloadBehavior GenericProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
Roberto Raggi's avatar
Roberto Raggi committed
633
{
634 635 636 637 638
    Q_UNUSED(state)
    Q_UNUSED(type)
    return BehaviorSilent;
}

639
bool GenericProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
640
{
641
    Q_UNUSED(errorString)
642 643
    Q_UNUSED(flag)
    Q_UNUSED(type)
644
    return true;
Roberto Raggi's avatar
Roberto Raggi committed
645
}