qtoptionspage.cpp 27.7 KB
Newer Older
Tobias Hunger's avatar
Tobias Hunger committed
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
Tobias Hunger's avatar
Tobias Hunger committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
**
** 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.
**
**************************************************************************/

30
31
32
#include "qtoptionspage.h"
#include "ui_showbuildlog.h"
#include "ui_qtversionmanager.h"
33
#include "qt4projectmanagerconstants.h"
34
#include "qt4target.h"
35
#include "qtversionmanager.h"
36

37
#include <projectexplorer/debugginghelper.h>
38
#include <coreplugin/coreconstants.h>
39
40
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
41
#include <utils/treewidgetcolumnstretcher.h>
42
#include <utils/qtcassert.h>
43
#include <qtconcurrent/runextensions.h>
44

45
46
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
47
#include <QtCore/QDebug>
48
#include <QtCore/QDir>
49
#include <QtCore/QSet>
50
#include <QtCore/QTextStream>
51
#include <QtCore/QDateTime>
52
53
#include <QtGui/QHelpEvent>
#include <QtGui/QToolTip>
54

55
56
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
57
58
59
60
61
62
63
64
65
66
67
68
69
70

///
// DebuggingHelperBuildTask
///

DebuggingHelperBuildTask::DebuggingHelperBuildTask(const QSharedPointerQtVersion &version) :
    m_version(version)
{
}

DebuggingHelperBuildTask::~DebuggingHelperBuildTask()
{
}

71
void DebuggingHelperBuildTask::run(QFutureInterface<void> &future)
72
{
73
74
    future.setProgressRange(0, 4);
    future.setProgressValue(1);
75
    const QString output = m_version->buildDebuggingHelperLibrary();
76
    future.setProgressValue(1);
77
    emit finished(m_version->displayName(), output);
78
79
80
    deleteLater();
}

81
82
83
84
85
///
// QtOptionsPage
///

QtOptionsPage::QtOptionsPage()
dt's avatar
dt committed
86
    : m_widget(0)
87
88
89
90
91
{
}

QString QtOptionsPage::id() const
{
92
    return QLatin1String(Constants::QTVERSION_SETTINGS_PAGE_ID);
93
94
}

95
QString QtOptionsPage::displayName() const
96
{
97
    return QCoreApplication::translate("Qt4ProjectManager", Constants::QTVERSION_SETTINGS_PAGE_NAME);
98
99
100
101
}

QString QtOptionsPage::category() const
{
102
    return QLatin1String(Constants::QT_SETTINGS_CATEGORY);
103
104
}

105
QString QtOptionsPage::displayCategory() const
106
{
107
    return QCoreApplication::translate("Qt4ProjectManager", Constants::QT_SETTINGS_TR_CATEGORY);
108
109
}

110
111
112
113
114
QIcon QtOptionsPage::categoryIcon() const
{
    return QIcon(QLatin1String(Constants::QT_SETTINGS_CATEGORY_ICON));
}

115
116
117
QWidget *QtOptionsPage::createPage(QWidget *parent)
{
    QtVersionManager *vm = QtVersionManager::instance();
Tobias Hunger's avatar
Tobias Hunger committed
118
    m_widget = new QtOptionsPageWidget(parent, vm->versions());
119
120
    if (m_searchKeywords.isEmpty())
        m_searchKeywords = m_widget->searchKeywords();
121
122
123
124
125
126
127
128
    return m_widget;
}

void QtOptionsPage::apply()
{
    m_widget->finish();

    QtVersionManager *vm = QtVersionManager::instance();
129
130
131
132
    // Turn into flat list
    QList<QtVersion *> versions;
    foreach(const QSharedPointerQtVersion &spv, m_widget->versions())
        versions.push_back(new QtVersion(*spv));
Tobias Hunger's avatar
Tobias Hunger committed
133
    vm->setNewQtVersions(versions);
134
135
}

136
137
138
139
140
bool QtOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

141
//-----------------------------------------------------
142
143


Tobias Hunger's avatar
Tobias Hunger committed
144
QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> versions)
145
    : QWidget(parent)
146
147
148
149
    , m_debuggingHelperOkPixmap(QLatin1String(":/extensionsystem/images/ok.png"))
    , m_debuggingHelperErrorPixmap(QLatin1String(":/extensionsystem/images/error.png"))
    , m_debuggingHelperOkIcon(m_debuggingHelperOkPixmap)
    , m_debuggingHelperErrorIcon(m_debuggingHelperErrorPixmap)
150
    , m_specifyNameString(tr("<specify a name>"))
151
    , m_specifyPathString(tr("<specify a qmake location>"))
152
    , m_ui(new Internal::Ui::QtVersionManager())
153
154
{
    // Initialize m_versions
155
156
    foreach(QtVersion *version, versions)
        m_versions.push_back(QSharedPointerQtVersion(new QtVersion(*version)));
157
158

    m_ui->setupUi(this);
159
    m_ui->qmakePath->setExpectedKind(Utils::PathChooser::File);
160
    m_ui->qmakePath->setPromptDialogTitle(tr("Select qmake Executable"));
161
    m_ui->mingwPath->setExpectedKind(Utils::PathChooser::Directory);
162
    m_ui->mingwPath->setPromptDialogTitle(tr("Select the MinGW Directory"));
163
    m_ui->mwcPath->setExpectedKind(Utils::PathChooser::Directory);
con's avatar
con committed
164
    m_ui->mwcPath->setPromptDialogTitle(tr("Select Carbide Install Directory"));
165
166
    m_ui->s60SDKPath->setExpectedKind(Utils::PathChooser::Directory);
    m_ui->s60SDKPath->setPromptDialogTitle(tr("Select S60 SDK Root"));
con's avatar
con committed
167
    m_ui->gccePath->setExpectedKind(Utils::PathChooser::Directory);
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
168
    m_ui->gccePath->setPromptDialogTitle(tr("Select the CSL ARM Toolchain (GCCE) Directory"));
169
170
171
172

    m_ui->addButton->setIcon(QIcon(Core::Constants::ICON_PLUS));
    m_ui->delButton->setIcon(QIcon(Core::Constants::ICON_MINUS));

173
    new Utils::TreeWidgetColumnStretcher(m_ui->qtdirList, 1);
174

175
176
177
    // setup parent items for auto-detected and manual versions
    m_ui->qtdirList->header()->setResizeMode(QHeaderView::ResizeToContents);
    QTreeWidgetItem *autoItem = new QTreeWidgetItem(m_ui->qtdirList);
178
    m_ui->qtdirList->installEventFilter(this);
179
180
181
182
183
184
    autoItem->setText(0, tr("Auto-detected"));
    autoItem->setFirstColumnSpanned(true);
    QTreeWidgetItem *manualItem = new QTreeWidgetItem(m_ui->qtdirList);
    manualItem->setText(0, tr("Manual"));
    manualItem->setFirstColumnSpanned(true);

185
    for (int i = 0; i < m_versions.count(); ++i) {
186
        const QtVersion * const version = m_versions.at(i).data();
187
        QTreeWidgetItem *item = new QTreeWidgetItem(version->isAutodetected()? autoItem : manualItem);
188
        item->setText(0, version->displayName());
189
        item->setText(1, QDir::toNativeSeparators(version->qmakeCommand()));
190
191
        item->setData(0, Qt::UserRole, version->uniqueId());

192
        if (version->isValid() && version->supportsBinaryDebuggingHelper())
193
            item->setData(2, Qt::DecorationRole, version->hasDebuggingHelper() ? m_debuggingHelperOkIcon : m_debuggingHelperErrorIcon);
Tobias Hunger's avatar
Tobias Hunger committed
194
        else
195
196
            item->setData(2, Qt::DecorationRole, QIcon());
    }
197
    m_ui->qtdirList->expandAll();
198
199
200
201
202

    connect(m_ui->nameEdit, SIGNAL(textEdited(const QString &)),
            this, SLOT(updateCurrentQtName()));


203
204
    connect(m_ui->qmakePath, SIGNAL(changed(QString)),
            this, SLOT(updateCurrentQMakeLocation()));
con's avatar
con committed
205
    connect(m_ui->mingwPath, SIGNAL(changed(QString)),
206
            this, SLOT(updateCurrentMingwDirectory()));
con's avatar
con committed
207
    connect(m_ui->mwcPath, SIGNAL(changed(QString)),
con's avatar
con committed
208
            this, SLOT(updateCurrentMwcDirectory()));
209
210
    connect(m_ui->s60SDKPath, SIGNAL(changed(QString)),
            this, SLOT(updateCurrentS60SDKDirectory()));
con's avatar
con committed
211
212
    connect(m_ui->gccePath, SIGNAL(changed(QString)),
            this, SLOT(updateCurrentGcceDirectory()));
213
214
215
216
217
218

    connect(m_ui->addButton, SIGNAL(clicked()),
            this, SLOT(addQtDir()));
    connect(m_ui->delButton, SIGNAL(clicked()),
            this, SLOT(removeQtDir()));

219
    connect(m_ui->qmakePath, SIGNAL(browsingFinished()),
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
            this, SLOT(onQtBrowsed()));
    connect(m_ui->mingwPath, SIGNAL(browsingFinished()),
            this, SLOT(onMingwBrowsed()));

    connect(m_ui->qtdirList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
            this, SLOT(versionChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
    connect(m_ui->msvcComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(msvcVersionChanged()));

    connect(m_ui->rebuildButton, SIGNAL(clicked()),
            this, SLOT(buildDebuggingHelper()));
    connect(m_ui->showLogButton, SIGNAL(clicked()),
            this, SLOT(showDebuggingBuildLog()));

    showEnvironmentPage(0);
    updateState();
}

238
239
240
241
242
bool QtOptionsPageWidget::eventFilter(QObject *o, QEvent *e)
{
    // Set the items tooltip, which may cause costly initialization
    // of QtVersion and must be up-to-date
    if (o != m_ui->qtdirList || e->type() != QEvent::ToolTip)
243
        return false;
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e);
    const QPoint treePos = helpEvent->pos() - QPoint(0, m_ui->qtdirList->header()->height());
    QTreeWidgetItem *item = m_ui->qtdirList->itemAt(treePos);
    if (!item)
        return false;
    const int index = indexForTreeItem(item);
    if (index == -1)
        return false;
    const QString tooltip = m_versions.at(index)->toHtml();
    QToolTip::showText(helpEvent->globalPos(), tooltip, m_ui->qtdirList);
    helpEvent->accept();
    return true;
}

258
int QtOptionsPageWidget::currentIndex() const
259
{
260
261
262
263
    if (QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem())
        return indexForTreeItem(currentItem);
    return -1;
}
264

265
266
267
268
269
270
271
QtVersion *QtOptionsPageWidget::currentVersion() const
{
    const int currentItemIndex = currentIndex();
    if (currentItemIndex >= 0 && currentItemIndex < m_versions.size())
        return m_versions.at(currentItemIndex).data();
    return 0;
}
272

273
274
275
276
static inline int findVersionByName(const QList<QSharedPointerQtVersion> &l, const QString &name)
{
    const int size = l.size();
    for (int i = 0; i < size; i++)
277
        if (l.at(i)->displayName() == name)
278
279
280
            return i;
    return -1;
}
281

282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// Update with results of terminated helper build
void QtOptionsPageWidget::debuggingHelperBuildFinished(const QString &name, const QString &output)
{
    const int index = findVersionByName(m_versions, name);
    if (index == -1)
        return; // Oops, somebody managed to delete the version
    // Update item view
    QTreeWidgetItem *item = treeItemForIndex(index);
    QTC_ASSERT(item, return)
    item->setData(2, Qt::UserRole, output);
    const bool success = m_versions.at(index)->hasDebuggingHelper();
    item->setData(2, Qt::DecorationRole, success ? m_debuggingHelperOkIcon : m_debuggingHelperErrorIcon);

    // Update bottom control if the selection is still the same
    if (index == currentIndex()) {
        m_ui->showLogButton->setEnabled(true);
        updateDebuggingHelperStateLabel(m_versions.at(index).data());
        if (!success)
            showDebuggingBuildLog();
301
    }
302
303
304
305
306
307
308
309
310
311
312
313
314
}

void QtOptionsPageWidget::buildDebuggingHelper()
{
    const int index = currentIndex();
    if (index < 0)
        return;

    m_ui->showLogButton->setEnabled(false);
    // Run a debugging helper build task in the background.
    DebuggingHelperBuildTask *buildTask = new DebuggingHelperBuildTask(m_versions.at(index));
    connect(buildTask, SIGNAL(finished(QString,QString)), this, SLOT(debuggingHelperBuildFinished(QString,QString)),
            Qt::QueuedConnection);
315
    QFuture<void> task = QtConcurrent::run(&DebuggingHelperBuildTask::run, buildTask);
316
317
    const QString taskName = tr("Building helpers");
    Core::ICore::instance()->progressManager()->addTask(task, taskName,
318
                                                        QLatin1String("Qt4ProjectManager::BuildHelpers"));
319
320
}

321
void QtOptionsPageWidget::showDebuggingBuildLog()
322
323
324
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();

325
326
327
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
328
    // Show and scroll to bottom
329
    QDialog dlg(this);
330
331
    Ui_ShowBuildLog ui;
    ui.setupUi(&dlg);
332
    ui.log->setPlainText(currentItem->data(2, Qt::UserRole).toString());
333
334
    ui.log->moveCursor(QTextCursor::End);
    ui.log->ensureCursorVisible();
335
336
337
    dlg.exec();
}

338
QtOptionsPageWidget::~QtOptionsPageWidget()
339
340
341
342
{
    delete m_ui;
}

343
void QtOptionsPageWidget::addQtDir()
344
{
345
    QSharedPointerQtVersion newVersion(new QtVersion(m_specifyNameString, m_specifyPathString));
346
347
    m_versions.append(newVersion);

348
    QTreeWidgetItem *item = new QTreeWidgetItem(m_ui->qtdirList->topLevelItem(1));
349
    item->setText(0, newVersion->displayName());
350
    item->setText(1, QDir::toNativeSeparators(newVersion->qmakeCommand()));
351
352
353
354
355
    item->setData(0, Qt::UserRole, newVersion->uniqueId());
    item->setData(2, Qt::DecorationRole, QIcon());

    m_ui->qtdirList->setCurrentItem(item);

356
    m_ui->nameEdit->setText(newVersion->displayName());
357
    m_ui->qmakePath->setPath(newVersion->qmakeCommand());
358
359
360
361
    m_ui->nameEdit->setFocus();
    m_ui->nameEdit->selectAll();
}

362
void QtOptionsPageWidget::removeQtDir()
363
364
{
    QTreeWidgetItem *item = m_ui->qtdirList->currentItem();
365
    int index = indexForTreeItem(item);
366
367
368
369
370
    if (index < 0)
        return;

    delete item;

371
    m_versions.removeAt(index);
372
373
374
    updateState();
}

375
376
377
// Format html table tooltip about helpers
static inline QString msgHtmlHelperToolTip(const QFileInfo &fi)
{
378
    //: Tooltip showing the debugging helper library file.
379
380
381
    return QtOptionsPageWidget::tr("<html><body><table><tr><td>File:</td><td><pre>%1</pre></td></tr>"
                                   "<tr><td>Last&nbsp;modified:</td><td>%2</td></tr>"
                                   "<tr><td>Size:</td><td>%3 Bytes</td></tr></table></body></html>").
382
                      arg(QDir::toNativeSeparators(fi.absoluteFilePath())).
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
                      arg(fi.lastModified().toString(Qt::SystemLocaleLongDate)).
                      arg(fi.size());
}

// Update the state label with a pixmap and set a tooltip describing
// the file on neighbouring controls.
void QtOptionsPageWidget::updateDebuggingHelperStateLabel(const QtVersion *version)
{
    QString tooltip;
    if (version && version->isValid()) {
        const bool hasHelper = version->hasDebuggingHelper();
        m_ui->debuggingHelperStateLabel->setPixmap(hasHelper ? m_debuggingHelperOkPixmap : m_debuggingHelperErrorPixmap);
        if (hasHelper)
            tooltip = msgHtmlHelperToolTip(QFileInfo(version->debuggingHelperLibrary()));
    } else {
        m_ui->debuggingHelperStateLabel->setPixmap(QPixmap());
    }
    m_ui->debuggingHelperStateLabel->setToolTip(tooltip);
    m_ui->debuggingHelperLabel->setToolTip(tooltip);
    m_ui->showLogButton->setToolTip(tooltip);
    m_ui->rebuildButton->setToolTip(tooltip);
}

406
void QtOptionsPageWidget::updateState()
407
{
408
409
410
    const QtVersion *version  = currentVersion();
    const bool enabled = version != 0;
    const bool isAutodetected = enabled && version->isAutodetected();
411
412
    m_ui->delButton->setEnabled(enabled && !isAutodetected);
    m_ui->nameEdit->setEnabled(enabled && !isAutodetected);
413
    m_ui->qmakePath->setEnabled(enabled && !isAutodetected);
414
    m_ui->mingwPath->setEnabled(enabled);
415
    m_ui->mwcPath->setEnabled(enabled);
416
417
418
    bool s60SDKPathEnabled = enabled &&
                             (isAutodetected ? version->s60SDKDirectory().isEmpty() : true);
    m_ui->s60SDKPath->setEnabled(s60SDKPathEnabled);
con's avatar
con committed
419
    m_ui->gccePath->setEnabled(enabled);
420

421
    const bool hasLog = enabled && !m_ui->qtdirList->currentItem()->data(2, Qt::UserRole).toString().isEmpty();
422
423
    m_ui->showLogButton->setEnabled(hasLog);

424
425
    m_ui->rebuildButton->setEnabled(version && version->isValid());
    updateDebuggingHelperStateLabel(version);
426
}
427

428
void QtOptionsPageWidget::makeMingwVisible(bool visible)
429
430
431
432
433
{
    m_ui->mingwLabel->setVisible(visible);
    m_ui->mingwPath->setVisible(visible);
}

434
435
436
437
438
439
440
void QtOptionsPageWidget::makeMSVCVisible(bool visible)
{
    m_ui->msvcLabel->setVisible(visible);
    m_ui->msvcComboBox->setVisible(visible);
    m_ui->msvcNotFoundLabel->setVisible(false);
}

441
void QtOptionsPageWidget::makeS60Visible(bool visible)
con's avatar
con committed
442
443
444
{
    m_ui->mwcLabel->setVisible(visible);
    m_ui->mwcPath->setVisible(visible);
445
446
    m_ui->s60SDKLabel->setVisible(visible);
    m_ui->s60SDKPath->setVisible(visible);
con's avatar
con committed
447
448
    m_ui->gcceLabel->setVisible(visible);
    m_ui->gccePath->setVisible(visible);
con's avatar
con committed
449
450
}

451
452
453
454
455
456
457
458
void QtOptionsPageWidget::makeDebuggingHelperVisible(bool visible)
{
    m_ui->debuggingHelperLabel->setVisible(visible);
    m_ui->debuggingHelperStateLabel->setVisible(visible);
    m_ui->showLogButton->setVisible(visible);
    m_ui->rebuildButton->setVisible(visible);
}

459
void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item)
460
461
{
    if (item) {
462
        int index = indexForTreeItem(item);
463
        m_ui->errorLabel->setText("");
464
465
466
        if (index < 0) {
            makeMSVCVisible(false);
            makeMingwVisible(false);
467
            makeS60Visible(false);
468
            makeDebuggingHelperVisible(false);
469
470
            return;
        }
471
472
473
        const QSharedPointerQtVersion qtVersion = m_versions.at(index);
        QList<ProjectExplorer::ToolChain::ToolChainType> types = qtVersion->possibleToolChainTypes();
        QSet<QString> targets = qtVersion->supportedTargetIds();
474
        makeDebuggingHelperVisible(qtVersion->supportsBinaryDebuggingHelper());
475
476
477
478
479
480
481
        if (types.isEmpty()) {
            makeMSVCVisible(false);
            makeMingwVisible(false);
            makeS60Visible(false);
            if (!m_versions.at(index)->isValid())
                m_ui->errorLabel->setText(m_versions.at(index)->invalidReason());
            else
dt's avatar
dt committed
482
                m_ui->errorLabel->setText(tr("This Qt Version has a unknown toolchain."));
483
        } else if (types.contains(ProjectExplorer::ToolChain::MinGW)) {
484
            makeMSVCVisible(false);
485
            makeMingwVisible(true);
486
            makeS60Visible(false);
487
            m_ui->mingwPath->setPath(m_versions.at(index)->mingwDirectory());
488
489
        } else if (types.contains(ProjectExplorer::ToolChain::MSVC) ||
                   types.contains(ProjectExplorer::ToolChain::WINCE)) {
490
            makeMSVCVisible(false);
491
            makeMingwVisible(false);
492
            makeS60Visible(false);
493
            const QStringList msvcEnvironments = ProjectExplorer::ToolChain::availableMSVCVersions(qtVersion->isQt64Bit());
494
            if (msvcEnvironments.count() == 0) {
495
496
                m_ui->msvcLabel->setVisible(true);
                m_ui->msvcNotFoundLabel->setVisible(true);
497
            } else {
498
                 makeMSVCVisible(true);
499
500
501
502
503
504
505
506
507
508
                 bool block = m_ui->msvcComboBox->blockSignals(true);
                 m_ui->msvcComboBox->clear();
                 foreach(const QString &msvcenv, msvcEnvironments) {
                     m_ui->msvcComboBox->addItem(msvcenv);
                     if (msvcenv == m_versions.at(index)->msvcVersion()) {
                         m_ui->msvcComboBox->setCurrentIndex(m_ui->msvcComboBox->count() - 1);
                     }
                 }
                 m_ui->msvcComboBox->blockSignals(block);
            }
509
510
        } else if (targets.contains(Constants::S60_DEVICE_TARGET_ID) ||
                   targets.contains(Constants::S60_EMULATOR_TARGET_ID)) {
con's avatar
con committed
511
512
            makeMSVCVisible(false);
            makeMingwVisible(false);
513
            makeS60Visible(true);
514
515
516
            m_ui->mwcPath->setPath(QDir::toNativeSeparators(m_versions.at(index)->mwcDirectory()));
            m_ui->s60SDKPath->setPath(QDir::toNativeSeparators(m_versions.at(index)->s60SDKDirectory()));
            m_ui->gccePath->setPath(QDir::toNativeSeparators(m_versions.at(index)->gcceDirectory()));
517
        } else { //ProjectExplorer::ToolChain::GCC
518
            makeMSVCVisible(false);
519
            makeMingwVisible(false);
520
            makeS60Visible(false);
521
        }
522

523
        if (m_ui->errorLabel->text().isEmpty()) {
524
            QString envs;
525
            if (targets.contains(Constants::DESKTOP_TARGET_ID))
526
                envs = tr("Desktop", "Qt Version is meant for the desktop");
527
528
            else if (targets.contains(Constants::S60_DEVICE_TARGET_ID) ||
                     targets.contains(Constants::S60_EMULATOR_TARGET_ID))
529
                envs = tr("Symbian", "Qt Version is meant for Symbian");
530
            else if (targets.contains(Constants::MAEMO_DEVICE_TARGET_ID))
531
                envs = tr("Maemo", "Qt Version is meant for Maemo");
532
533
            else if (targets.contains(Constants::QT_SIMULATOR_TARGET_ID))
                envs = tr("Qt Simulator", "Qt Version is meant for Qt Simulator");
534
535
536
537
538
            else
                envs = tr("unkown", "No idea what this Qt Version is meant for!");
            m_ui->errorLabel->setText(tr("Found Qt version %1, using mkspec %2 (%3)")
                                      .arg(m_versions.at(index)->qtVersionString(),
                                           m_versions.at(index)->mkspec(), envs));
539
540
        }
    } else {
541
        makeMSVCVisible(false);
542
        makeMingwVisible(false);
543
        makeS60Visible(false);
544
        makeDebuggingHelperVisible(false);
545
546
547
    }
}

548
int QtOptionsPageWidget::indexForTreeItem(const QTreeWidgetItem *item) const
549
550
551
{
    if (!item || !item->parent())
        return -1;
552
    const int uniqueId = item->data(0, Qt::UserRole).toInt();
553
554
555
556
557
558
559
    for (int index = 0; index < m_versions.size(); ++index) {
        if (m_versions.at(index)->uniqueId() == uniqueId)
            return index;
    }
    return -1;
}

560
561
QTreeWidgetItem *QtOptionsPageWidget::treeItemForIndex(int index) const
{
562
    const int uniqueId = m_versions.at(index)->uniqueId();
563
564
565
566
567
568
569
570
571
572
573
574
    for (int i = 0; i < m_ui->qtdirList->topLevelItemCount(); ++i) {
        QTreeWidgetItem *toplevelItem = m_ui->qtdirList->topLevelItem(i);
        for (int j = 0; j < toplevelItem->childCount(); ++j) {
            QTreeWidgetItem *item = toplevelItem->child(j);
            if (item->data(0, Qt::UserRole).toInt() == uniqueId) {
                return item;
            }
        }
    }
    return 0;
}

575
void QtOptionsPageWidget::versionChanged(QTreeWidgetItem *item, QTreeWidgetItem *old)
576
577
{
    if (old) {
578
        fixQtVersionName(indexForTreeItem(old));
579
    }
580
581
    int itemIndex = indexForTreeItem(item);
    if (itemIndex >= 0) {
582
        m_ui->nameEdit->setText(item->text(0));
583
        m_ui->qmakePath->setPath(item->text(1));
584
585
    } else {
        m_ui->nameEdit->clear();
586
        m_ui->qmakePath->setPath(QString()); // clear()
587
588
589
590
591
    }
    showEnvironmentPage(item);
    updateState();
}

592
void QtOptionsPageWidget::onQtBrowsed()
593
{
594
    const QString dir = m_ui->qmakePath->path();
595
596
597
    if (dir.isEmpty())
        return;

598
    updateCurrentQMakeLocation();
599
    if (m_ui->nameEdit->text().isEmpty() || m_ui->nameEdit->text() == m_specifyNameString) {
600
601
602
        QString name = ProjectExplorer::DebuggingHelperLibrary::qtVersionForQMake(QDir::cleanPath(dir));
        if (!name.isEmpty())
            m_ui->nameEdit->setText(name);
603
604
605
606
607
        updateCurrentQtName();
    }
    updateState();
}

608
void QtOptionsPageWidget::onMingwBrowsed()
609
610
611
612
613
614
615
616
617
{
    const QString dir = m_ui->mingwPath->path();
    if (dir.isEmpty())
        return;

    updateCurrentMingwDirectory();
    updateState();
}

618
void QtOptionsPageWidget::updateCurrentQtName()
619
620
621
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
622
623
624
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
625
626
    m_versions[currentItemIndex]->setDisplayName(m_ui->nameEdit->text());
    currentItem->setText(0, m_versions[currentItemIndex]->displayName());
627
628
629
}


630
void QtOptionsPageWidget::finish()
631
632
{
    if (QTreeWidgetItem *item = m_ui->qtdirList->currentItem())
633
        fixQtVersionName(indexForTreeItem(item));
634
635
636
637
638
639
}

/* Checks that the qt version name is unique
 * and otherwise changes the name
 *
 */
640
void QtOptionsPageWidget::fixQtVersionName(int index)
641
{
642
643
    if (index < 0)
        return;
644
    int count = m_versions.count();
645
    QString name = m_versions.at(index)->displayName();
646
647
    for (int i = 0; i < count; ++i) {
        if (i != index) {
648
            if (m_versions.at(i)->displayName() == m_versions.at(index)->displayName()) {
649
650
651
                // Same name, find new name
                QRegExp regexp("^(.*)\\((\\d)\\)$");
                if (regexp.exactMatch(name)) {
Tobias Hunger's avatar
Tobias Hunger committed
652
                    // Already in Name (#) format
653
654
655
656
                    name = regexp.cap(1);
                    name += QLatin1Char('(');
                    name += QString::number(regexp.cap(2).toInt() + 1);
                    name += QLatin1Char(')');
657
                } else {
658
                    name +=  QLatin1String(" (2)");
659
660
                }
                // set new name
661
                m_versions[index]->setDisplayName(name);
662
                treeItemForIndex(index)->setText(0, name);
663
664
665
666
667
668
669
670

                // Now check again...
                fixQtVersionName(index);
            }
        }
    }
}

671
void QtOptionsPageWidget::updateCurrentQMakeLocation()
672
673
674
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
675
676
677
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
678
    QtVersion *version = m_versions.at(currentItemIndex).data();
679
    if (version->qmakeCommand() == m_ui->qmakePath->path())
680
        return;
681
682
    version->setQMakeCommand(m_ui->qmakePath->path());
    currentItem->setText(1, QDir::toNativeSeparators(version->qmakeCommand()));
683
684
    showEnvironmentPage(currentItem);

685
    if (version->isValid() && version->supportsBinaryDebuggingHelper()) {
686
687
        const bool hasLog = !currentItem->data(2, Qt::UserRole).toString().isEmpty();
        currentItem->setData(2, Qt::DecorationRole, version->hasDebuggingHelper() ? m_debuggingHelperOkIcon : m_debuggingHelperErrorIcon);
688
        m_ui->showLogButton->setEnabled(hasLog);
689
        m_ui->rebuildButton->setEnabled(true);
690
691
    } else {
        currentItem->setData(2, Qt::DecorationRole, QIcon());
692
        m_ui->rebuildButton->setEnabled(false);
693
    }
694
    updateDebuggingHelperStateLabel(version);
695
696
}

697
void QtOptionsPageWidget::updateCurrentMingwDirectory()
698
699
700
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
701
702
703
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
704
705
706
    m_versions[currentItemIndex]->setMingwDirectory(m_ui->mingwPath->path());
}

707
void QtOptionsPageWidget::msvcVersionChanged()
708
709
710
711
{
    const QString &msvcVersion = m_ui->msvcComboBox->currentText();
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
712
713
714
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
715
716
717
    m_versions[currentItemIndex]->setMsvcVersion(msvcVersion);
}

con's avatar
con committed
718
719
720
721
722
723
724
void QtOptionsPageWidget::updateCurrentMwcDirectory()
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
725
726
    m_versions[currentItemIndex]->setMwcDirectory(
            QDir::fromNativeSeparators(m_ui->mwcPath->path()));
con's avatar
con committed
727
}
728
729
730
731
732
733
734
void QtOptionsPageWidget::updateCurrentS60SDKDirectory()
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
735
736
    m_versions[currentItemIndex]->setS60SDKDirectory(
            QDir::fromNativeSeparators(m_ui->s60SDKPath->path()));
737
}
con's avatar
con committed
738
739
740
741
742
743
744
void QtOptionsPageWidget::updateCurrentGcceDirectory()
{
    QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
    Q_ASSERT(currentItem);
    int currentItemIndex = indexForTreeItem(currentItem);
    if (currentItemIndex < 0)
        return;
745
746
    m_versions[currentItemIndex]->setGcceDirectory(
            QDir::fromNativeSeparators(m_ui->gccePath->path()));
con's avatar
con committed
747
}
con's avatar
con committed
748

749
QList<QSharedPointerQtVersion> QtOptionsPageWidget::versions() const
750
751
752
753
{
    return m_versions;
}

754
755
756
757
758
759
760
QString QtOptionsPageWidget::searchKeywords() const
{
    QString rc;
    QTextStream(&rc) << ' ' << m_ui->mingwLabel->text()
            << ' ' << m_ui->msvcLabel->text()
            << ' ' << m_ui->gcceLabel->text()
            << ' ' << m_ui->mwcLabel->text()
761
            << ' ' << m_ui->debuggingHelperLabel->text();
762
763
764
    rc.remove(QLatin1Char('&'));
    return rc;
}