Newer
Older
#include "qtoptionspage.h"
#include "ui_showbuildlog.h"
#include "ui_qtversionmanager.h"
#include "qt4projectmanagerconstants.h"
#include "qtversionmanager.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/treewidgetcolumnstretcher.h>
#include <utils/qtcassert.h>
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QDateTime>
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
///
// DebuggingHelperBuildTask
///
DebuggingHelperBuildTask::DebuggingHelperBuildTask(const QSharedPointerQtVersion &version) :
m_version(version)
{
}
DebuggingHelperBuildTask::~DebuggingHelperBuildTask()
{
}
void DebuggingHelperBuildTask::run()
{
const QString output = m_version->buildDebuggingHelperLibrary();
emit finished(m_version->name(), output);
deleteLater();
}
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
///
// QtOptionsPage
///
QtOptionsPage::QtOptionsPage()
{
}
QtOptionsPage::~QtOptionsPage()
{
}
QString QtOptionsPage::id() const
{
return QLatin1String(Constants::QTVERSION_PAGE);
}
QString QtOptionsPage::trName() const
{
return tr(Constants::QTVERSION_PAGE);
}
QString QtOptionsPage::category() const
{
return Constants::QT_CATEGORY;
}
QString QtOptionsPage::trCategory() const
{
return tr(Constants::QT_CATEGORY);
}
QWidget *QtOptionsPage::createPage(QWidget *parent)
{
QtVersionManager *vm = QtVersionManager::instance();
m_widget = new QtOptionsPageWidget(parent, vm->versions(), vm->currentQtVersion());
return m_widget;
}
void QtOptionsPage::apply()
{
m_widget->finish();
QtVersionManager *vm = QtVersionManager::instance();
// Turn into flat list
QList<QtVersion *> versions;
foreach(const QSharedPointerQtVersion &spv, m_widget->versions())
versions.push_back(new QtVersion(*spv));
vm->setNewQtVersions(versions, m_widget->defaultVersion());
}
//-----------------------------------------------------
QtOptionsPageWidget::QtOptionsPageWidget(QWidget *parent, QList<QtVersion *> versions, QtVersion *defaultVersion)
, m_debuggingHelperOkPixmap(QLatin1String(":/extensionsystem/images/ok.png"))
, m_debuggingHelperErrorPixmap(QLatin1String(":/extensionsystem/images/error.png"))
, m_debuggingHelperOkIcon(m_debuggingHelperOkPixmap)
, m_debuggingHelperErrorIcon(m_debuggingHelperErrorPixmap)
, m_specifyNameString(tr("<specify a name>"))
, m_specifyPathString(tr("<specify a path>"))
, m_ui(new Internal::Ui::QtVersionManager())
, m_defaultVersion(versions.indexOf(defaultVersion))
{
// Initialize m_versions
foreach(QtVersion *version, versions)
m_versions.push_back(QSharedPointerQtVersion(new QtVersion(*version)));
m_ui->setupUi(this);
m_ui->qtPath->setExpectedKind(Core::Utils::PathChooser::Directory);
m_ui->qtPath->setPromptDialogTitle(tr("Select QTDIR"));
m_ui->mingwPath->setExpectedKind(Core::Utils::PathChooser::Directory);
m_ui->qtPath->setPromptDialogTitle(tr("Select the Qt Directory"));
m_ui->mwcPath->setExpectedKind(Core::Utils::PathChooser::Directory);
m_ui->mwcPath->setPromptDialogTitle(tr("Select \"x86build\" Directory from Carbide Install"));
m_ui->addButton->setIcon(QIcon(Core::Constants::ICON_PLUS));
m_ui->delButton->setIcon(QIcon(Core::Constants::ICON_MINUS));
new Core::Utils::TreeWidgetColumnStretcher(m_ui->qtdirList, 1);
// setup parent items for auto-detected and manual versions
m_ui->qtdirList->header()->setResizeMode(QHeaderView::ResizeToContents);
QTreeWidgetItem *autoItem = new QTreeWidgetItem(m_ui->qtdirList);
autoItem->setText(0, tr("Auto-detected"));
autoItem->setFirstColumnSpanned(true);
QTreeWidgetItem *manualItem = new QTreeWidgetItem(m_ui->qtdirList);
manualItem->setText(0, tr("Manual"));
manualItem->setFirstColumnSpanned(true);
for (int i = 0; i < m_versions.count(); ++i) {
const QtVersion * const version = m_versions.at(i).data();
QTreeWidgetItem *item = new QTreeWidgetItem(version->isAutodetected()? autoItem : manualItem);
item->setText(0, version->name());
item->setText(1, QDir::toNativeSeparators(version->path()));
item->setData(0, Qt::UserRole, version->uniqueId());
if (version->isValid()) {
item->setData(2, Qt::DecorationRole, version->hasDebuggingHelper() ? m_debuggingHelperOkIcon : m_debuggingHelperErrorIcon);
} else {
item->setData(2, Qt::DecorationRole, QIcon());
}
m_ui->defaultCombo->addItem(version->name());
if (i == m_defaultVersion)
m_ui->defaultCombo->setCurrentIndex(i);
}
m_ui->qtdirList->expandAll();
connect(m_ui->nameEdit, SIGNAL(textEdited(const QString &)),
this, SLOT(updateCurrentQtName()));
this, SLOT(updateCurrentQtPath()));
this, SLOT(updateCurrentMingwDirectory()));
this, SLOT(updateCurrentMwcDirectory()));
#endif
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
connect(m_ui->addButton, SIGNAL(clicked()),
this, SLOT(addQtDir()));
connect(m_ui->delButton, SIGNAL(clicked()),
this, SLOT(removeQtDir()));
connect(m_ui->qtPath, SIGNAL(browsingFinished()),
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->defaultCombo, SIGNAL(currentIndexChanged(int)),
this, SLOT(defaultChanged(int)));
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();
}
int QtOptionsPageWidget::currentIndex() const
if (QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem())
return indexForTreeItem(currentItem);
return -1;
}
QtVersion *QtOptionsPageWidget::currentVersion() const
{
const int currentItemIndex = currentIndex();
if (currentItemIndex >= 0 && currentItemIndex < m_versions.size())
return m_versions.at(currentItemIndex).data();
return 0;
}
static inline int findVersionByName(const QList<QSharedPointerQtVersion> &l, const QString &name)
{
const int size = l.size();
for (int i = 0; i < size; i++)
if (l.at(i)->name() == name)
return i;
return -1;
}
// 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();
}
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);
QFuture<void> task = QtConcurrent::run(buildTask, &DebuggingHelperBuildTask::run);
const QString taskName = tr("Building helpers");
Core::ICore::instance()->progressManager()->addTask(task, taskName,
QLatin1String("Qt4ProjectManager::BuildHelpers"),
Core::ProgressManager::CloseOnSuccess);
void QtOptionsPageWidget::showDebuggingBuildLog()
{
QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
int currentItemIndex = indexForTreeItem(currentItem);
if (currentItemIndex < 0)
return;
// Show and scroll to bottom
QDialog dlg;
Ui_ShowBuildLog ui;
ui.setupUi(&dlg);
ui.log->setPlainText(currentItem->data(2, Qt::UserRole).toString());
ui.log->moveCursor(QTextCursor::End);
ui.log->ensureCursorVisible();
dlg.exec();
}
QtOptionsPageWidget::~QtOptionsPageWidget()
{
delete m_ui;
}
void QtOptionsPageWidget::addQtDir()
QSharedPointerQtVersion newVersion(new QtVersion(m_specifyNameString, m_specifyPathString));
m_versions.append(newVersion);
QTreeWidgetItem *item = new QTreeWidgetItem(m_ui->qtdirList->topLevelItem(1));
item->setText(0, newVersion->name());
item->setText(1, QDir::toNativeSeparators(newVersion->path()));
item->setData(0, Qt::UserRole, newVersion->uniqueId());
item->setData(2, Qt::DecorationRole, QIcon());
m_ui->qtdirList->setCurrentItem(item);
m_ui->nameEdit->setText(newVersion->name());
m_ui->qtPath->setPath(newVersion->path());
m_ui->defaultCombo->addItem(newVersion->name());
m_ui->nameEdit->setFocus();
m_ui->nameEdit->selectAll();
}
void QtOptionsPageWidget::removeQtDir()
{
QTreeWidgetItem *item = m_ui->qtdirList->currentItem();
int index = indexForTreeItem(item);
if (index < 0)
return;
for (int i = 0; i < m_ui->defaultCombo->count(); ++i) {
if (m_ui->defaultCombo->itemText(i) == item->text(0)) {
m_ui->defaultCombo->removeItem(i);
break;
}
}
delete item;
m_versions.removeAt(index);
updateState();
}
// Format html table tooltip about helpers
static inline QString msgHtmlHelperToolTip(const QFileInfo &fi)
{
//: Tooltip showing the debugging helper library file.
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
return QtOptionsPageWidget::tr("<html><body><table><tr><td>File:</td><td><pre>%1</pre></td></tr>"
"<tr><td>Last modified:</td><td>%2</td></tr>"
"<tr><td>Size:</td><td>%3 Bytes</td></tr></table></body></html>").
arg(fi.absoluteFilePath()).
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);
}
void QtOptionsPageWidget::updateState()
const QtVersion *version = currentVersion();
const bool enabled = version != 0;
const bool isAutodetected = enabled && version->isAutodetected();
m_ui->delButton->setEnabled(enabled && !isAutodetected);
m_ui->nameEdit->setEnabled(enabled && !isAutodetected);
m_ui->qtPath->setEnabled(enabled && !isAutodetected);
m_ui->mingwPath->setEnabled(enabled);
const bool hasLog = enabled && !m_ui->qtdirList->currentItem()->data(2, Qt::UserRole).toString().isEmpty();
m_ui->showLogButton->setEnabled(hasLog);
m_ui->rebuildButton->setEnabled(version && version->isValid());
updateDebuggingHelperStateLabel(version);
void QtOptionsPageWidget::makeMingwVisible(bool visible)
{
m_ui->mingwLabel->setVisible(visible);
m_ui->mingwPath->setVisible(visible);
}
void QtOptionsPageWidget::makeMSVCVisible(bool visible)
{
m_ui->msvcLabel->setVisible(visible);
m_ui->msvcComboBox->setVisible(visible);
m_ui->msvcNotFoundLabel->setVisible(false);
}
void QtOptionsPageWidget::makeMWCVisible(bool visible)
{
m_ui->mwcLabel->setVisible(visible);
m_ui->mwcPath->setVisible(visible);
}
void QtOptionsPageWidget::showEnvironmentPage(QTreeWidgetItem *item)
int index = indexForTreeItem(item);
if (index < 0) {
makeMSVCVisible(false);
makeMingwVisible(false);
m_ui->errorLabel->setText("");
QList<ProjectExplorer::ToolChain::ToolChainType> types = m_versions.at(index)->possibleToolChainTypes();
if (types.contains(ProjectExplorer::ToolChain::MinGW)) {
makeMSVCVisible(false);
makeMingwVisible(true);
m_ui->mingwPath->setPath(m_versions.at(index)->mingwDirectory());
} else if (types.contains(ProjectExplorer::ToolChain::MSVC) || types.contains(ProjectExplorer::ToolChain::WINCE)){
makeMSVCVisible(false);
makeMingwVisible(false);
QStringList msvcEnvironments = ProjectExplorer::ToolChain::availableMSVCVersions();
if (msvcEnvironments.count() == 0) {
m_ui->msvcLabel->setVisible(true);
m_ui->msvcNotFoundLabel->setVisible(true);
makeMSVCVisible(true);
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);
}
} else if (types.contains(ProjectExplorer::ToolChain::WINSCW)) {
makeMSVCVisible(false);
makeMingwVisible(false);
makeMWCVisible(true);
m_ui->mwcPath->setPath(m_versions.at(index)->mwcDirectory());
#endif
} else if (types.contains(ProjectExplorer::ToolChain::INVALID)) {
makeMSVCVisible(false);
makeMingwVisible(false);
if (!m_versions.at(index)->isInstalled())
m_ui->errorLabel->setText(tr("The Qt Version %1 is not installed. Run make install")
.arg(QDir::toNativeSeparators(m_versions.at(index)->path())));
else
m_ui->errorLabel->setText(tr("%1 is not a valid Qt directory").arg(QDir::toNativeSeparators(m_versions.at(index)->path())));
} else { //ProjectExplorer::ToolChain::GCC
makeMSVCVisible(false);
makeMingwVisible(false);
m_ui->errorLabel->setText(tr("Found Qt version %1, using mkspec %2")
.arg(m_versions.at(index)->qtVersionString(),
m_versions.at(index)->mkspec()));
}
} else {
makeMSVCVisible(false);
makeMingwVisible(false);
int QtOptionsPageWidget::indexForTreeItem(const QTreeWidgetItem *item) const
{
if (!item || !item->parent())
return -1;
const int uniqueId = item->data(0, Qt::UserRole).toInt();
for (int index = 0; index < m_versions.size(); ++index) {
if (m_versions.at(index)->uniqueId() == uniqueId)
return index;
}
return -1;
}
QTreeWidgetItem *QtOptionsPageWidget::treeItemForIndex(int index) const
{
const int uniqueId = m_versions.at(index)->uniqueId();
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;
}
void QtOptionsPageWidget::versionChanged(QTreeWidgetItem *item, QTreeWidgetItem *old)
fixQtVersionName(indexForTreeItem(old));
int itemIndex = indexForTreeItem(item);
if (itemIndex >= 0) {
m_ui->nameEdit->setText(item->text(0));
m_ui->qtPath->setPath(item->text(1));
} else {
m_ui->nameEdit->clear();
m_ui->qtPath->setPath(QString()); // clear()
}
showEnvironmentPage(item);
updateState();
}
void QtOptionsPageWidget::onQtBrowsed()
{
const QString dir = m_ui->qtPath->path();
if (dir.isEmpty())
return;
updateCurrentQtPath();
if (m_ui->nameEdit->text().isEmpty() || m_ui->nameEdit->text() == m_specifyNameString) {
QStringList dirSegments = dir.split(QDir::separator(), QString::SkipEmptyParts);
if (!dirSegments.isEmpty())
m_ui->nameEdit->setText(dirSegments.last());
updateCurrentQtName();
}
updateState();
}
void QtOptionsPageWidget::onMingwBrowsed()
{
const QString dir = m_ui->mingwPath->path();
if (dir.isEmpty())
return;
updateCurrentMingwDirectory();
updateState();
}
void QtOptionsPageWidget::defaultChanged(int)
{
for (int i=0; i<m_ui->defaultCombo->count(); ++i) {
if (m_versions.at(i)->name() == m_ui->defaultCombo->currentText()) {
m_defaultVersion = i;
return;
}
}
m_defaultVersion = 0;
}
void QtOptionsPageWidget::updateCurrentQtName()
{
QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
Q_ASSERT(currentItem);
int currentItemIndex = indexForTreeItem(currentItem);
if (currentItemIndex < 0)
return;
m_versions[currentItemIndex]->setName(m_ui->nameEdit->text());
currentItem->setText(0, m_versions[currentItemIndex]->name());
m_ui->defaultCombo->setItemText(currentItemIndex, m_versions[currentItemIndex]->name());
}
void QtOptionsPageWidget::finish()
{
if (QTreeWidgetItem *item = m_ui->qtdirList->currentItem())
fixQtVersionName(indexForTreeItem(item));
}
/* Checks that the qt version name is unique
* and otherwise changes the name
*
*/
void QtOptionsPageWidget::fixQtVersionName(int index)
if (index < 0)
return;
int count = m_versions.count();
QString name = m_versions.at(index)->name();
for (int i = 0; i < count; ++i) {
if (i != index) {
if (m_versions.at(i)->name() == m_versions.at(index)->name()) {
// Same name, find new name
QRegExp regexp("^(.*)\\((\\d)\\)$");
if (regexp.exactMatch(name)) {
// Alreay in Name (#) format
name = regexp.cap(1) + "(" + QString().setNum(regexp.cap(2).toInt() + 1) + ")";
} else {
name = name + " (2)";
}
// set new name
m_versions[index]->setName(name);
treeItemForIndex(index)->setText(0, name);
m_ui->defaultCombo->setItemText(index, name);
// Now check again...
fixQtVersionName(index);
}
}
}
}
void QtOptionsPageWidget::updateCurrentQtPath()
{
QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
Q_ASSERT(currentItem);
int currentItemIndex = indexForTreeItem(currentItem);
if (currentItemIndex < 0)
return;
QtVersion *version = m_versions.at(currentItemIndex).data();
if (version->path() == m_ui->qtPath->path())
version->setPath(m_ui->qtPath->path());
currentItem->setText(1, QDir::toNativeSeparators(version->path()));
showEnvironmentPage(currentItem);
if (version->isValid()) {
const bool hasLog = !currentItem->data(2, Qt::UserRole).toString().isEmpty();
currentItem->setData(2, Qt::DecorationRole, version->hasDebuggingHelper() ? m_debuggingHelperOkIcon : m_debuggingHelperErrorIcon);
m_ui->showLogButton->setEnabled(hasLog);
m_ui->rebuildButton->setEnabled(true);
} else {
currentItem->setData(2, Qt::DecorationRole, QIcon());
m_ui->rebuildButton->setEnabled(false);
updateDebuggingHelperStateLabel(version);
void QtOptionsPageWidget::updateCurrentMingwDirectory()
{
QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
Q_ASSERT(currentItem);
int currentItemIndex = indexForTreeItem(currentItem);
if (currentItemIndex < 0)
return;
m_versions[currentItemIndex]->setMingwDirectory(m_ui->mingwPath->path());
}
void QtOptionsPageWidget::msvcVersionChanged()
{
const QString &msvcVersion = m_ui->msvcComboBox->currentText();
QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
Q_ASSERT(currentItem);
int currentItemIndex = indexForTreeItem(currentItem);
if (currentItemIndex < 0)
return;
m_versions[currentItemIndex]->setMsvcVersion(msvcVersion);
}
#ifdef QTCREATOR_WITH_S60
void QtOptionsPageWidget::updateCurrentMwcDirectory()
{
QTreeWidgetItem *currentItem = m_ui->qtdirList->currentItem();
Q_ASSERT(currentItem);
int currentItemIndex = indexForTreeItem(currentItem);
if (currentItemIndex < 0)
return;
m_versions[currentItemIndex]->setMwcDirectory(m_ui->mwcPath->path());
}
#endif
QList<QSharedPointerQtVersion> QtOptionsPageWidget::versions() const
{
return m_versions;
}
int QtOptionsPageWidget::defaultVersion() const
{
return m_defaultVersion;
}