2013-10-25 13:47:08 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** 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 "debuggeroptionspage.h"
|
|
|
|
|
|
|
|
|
|
#include "debuggeritemmanager.h"
|
|
|
|
|
#include "debuggeritemmodel.h"
|
|
|
|
|
|
|
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/detailswidget.h>
|
|
|
|
|
#include <utils/pathchooser.h>
|
|
|
|
|
#include <utils/qtcassert.h>
|
2013-10-29 07:26:11 +01:00
|
|
|
#include <utils/winutils.h>
|
2013-10-25 13:47:08 +02:00
|
|
|
|
2013-11-27 12:32:43 +01:00
|
|
|
#include <QFileInfo>
|
2013-10-25 13:47:08 +02:00
|
|
|
#include <QFormLayout>
|
|
|
|
|
#include <QHeaderView>
|
|
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
#include <QObject>
|
|
|
|
|
#include <QPushButton>
|
|
|
|
|
#include <QTreeView>
|
|
|
|
|
#include <QWidget>
|
|
|
|
|
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
|
|
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
static const char debuggingToolsWikiLinkC[] = "http://qt-project.org/wiki/Qt_Creator_Windows_Debugging";
|
|
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
|
// DebuggerItemConfigWidget
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
|
|
2013-10-28 14:05:12 +01:00
|
|
|
DebuggerItemConfigWidget::DebuggerItemConfigWidget(DebuggerItemModel *model) :
|
|
|
|
|
m_model(model)
|
2013-10-25 13:47:08 +02:00
|
|
|
{
|
2013-10-28 14:05:12 +01:00
|
|
|
QTC_CHECK(model);
|
|
|
|
|
|
2013-10-25 13:47:08 +02:00
|
|
|
m_displayNameLineEdit = new QLineEdit(this);
|
|
|
|
|
|
|
|
|
|
m_binaryChooser = new PathChooser(this);
|
|
|
|
|
m_binaryChooser->setExpectedKind(PathChooser::ExistingCommand);
|
|
|
|
|
m_binaryChooser->setMinimumWidth(400);
|
2013-10-28 18:19:38 +01:00
|
|
|
m_binaryChooser->setHistoryCompleter(QLatin1String("DebuggerPaths"));
|
2013-11-27 12:32:43 +01:00
|
|
|
connect(m_binaryChooser, SIGNAL(changed(QString)), this, SLOT(commandWasChanged()));
|
2013-10-25 13:47:08 +02:00
|
|
|
|
|
|
|
|
m_cdbLabel = new QLabel(this);
|
|
|
|
|
m_cdbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
|
|
|
|
m_cdbLabel->setOpenExternalLinks(true);
|
|
|
|
|
|
|
|
|
|
m_abis = new QLineEdit(this);
|
|
|
|
|
m_abis->setEnabled(false);
|
|
|
|
|
|
|
|
|
|
QFormLayout *formLayout = new QFormLayout(this);
|
|
|
|
|
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
|
|
|
|
formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
|
|
|
|
|
// formLayout->addRow(new QLabel(tr("Type:")), m_engineTypeComboBox);
|
|
|
|
|
formLayout->addRow(m_cdbLabel);
|
|
|
|
|
formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
|
|
|
|
|
formLayout->addRow(new QLabel(tr("ABIs:")), m_abis);
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-27 12:32:43 +01:00
|
|
|
DebuggerItem DebuggerItemConfigWidget::item() const
|
2013-11-12 15:11:04 +01:00
|
|
|
{
|
|
|
|
|
DebuggerItem item(m_id);
|
|
|
|
|
if (m_id.isNull())
|
|
|
|
|
return item;
|
|
|
|
|
|
|
|
|
|
item.setDisplayName(m_displayNameLineEdit->text());
|
|
|
|
|
item.setCommand(m_binaryChooser->fileName());
|
|
|
|
|
item.setAutoDetected(m_autodetected);
|
2013-11-27 12:32:43 +01:00
|
|
|
QList<ProjectExplorer::Abi> abiList;
|
|
|
|
|
foreach (const QString &a, m_abis->text().split(QRegExp(QLatin1String("[^A-Za-z0-9-_]+")))) {
|
|
|
|
|
ProjectExplorer::Abi abi(a);
|
|
|
|
|
if (a.isNull())
|
|
|
|
|
continue;
|
|
|
|
|
abiList << a;
|
|
|
|
|
}
|
|
|
|
|
item.setAbis(abiList);
|
2013-11-12 15:11:04 +01:00
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-27 12:32:43 +01:00
|
|
|
|
|
|
|
|
void DebuggerItemConfigWidget::store() const
|
|
|
|
|
{
|
2013-12-04 12:34:48 +01:00
|
|
|
DebuggerItem i = item();
|
|
|
|
|
if (i.isValid())
|
|
|
|
|
m_model->updateDebugger(i);
|
2013-11-27 12:32:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerItemConfigWidget::setAbis(const QStringList &abiNames)
|
|
|
|
|
{
|
|
|
|
|
m_abis->setText(abiNames.join(QLatin1String(", ")));
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
void DebuggerItemConfigWidget::setItem(const DebuggerItem &item)
|
2013-10-25 13:47:08 +02:00
|
|
|
{
|
2013-11-12 15:11:04 +01:00
|
|
|
store(); // store away the (changed) settings for future use
|
|
|
|
|
|
|
|
|
|
m_autodetected = item.isAutoDetected();
|
|
|
|
|
m_id = item.id();
|
|
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
m_displayNameLineEdit->setEnabled(!item.isAutoDetected());
|
|
|
|
|
m_displayNameLineEdit->setText(item.displayName());
|
2013-10-25 13:47:08 +02:00
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
m_binaryChooser->setEnabled(!item.isAutoDetected());
|
|
|
|
|
m_binaryChooser->setFileName(item.command());
|
2013-10-25 13:47:08 +02:00
|
|
|
|
|
|
|
|
QString text;
|
|
|
|
|
QString versionCommand;
|
2013-10-28 17:47:37 +01:00
|
|
|
if (item.engineType() == CdbEngineType) {
|
2013-10-25 13:47:08 +02:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
const bool is64bit = winIs64BitSystem();
|
|
|
|
|
#else
|
|
|
|
|
const bool is64bit = false;
|
|
|
|
|
#endif
|
|
|
|
|
const QString versionString = is64bit ? tr("64-bit version") : tr("32-bit version");
|
|
|
|
|
//: Label text for path configuration. %2 is "x-bit version".
|
|
|
|
|
text = tr("<html><body><p>Specify the path to the "
|
|
|
|
|
"<a href=\"%1\">Windows Console Debugger executable</a>"
|
|
|
|
|
" (%2) here.</p>""</body></html>").
|
|
|
|
|
arg(QLatin1String(debuggingToolsWikiLinkC), versionString);
|
|
|
|
|
versionCommand = QLatin1String("-version");
|
|
|
|
|
} else {
|
|
|
|
|
versionCommand = QLatin1String("--version");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_cdbLabel->setText(text);
|
|
|
|
|
m_cdbLabel->setVisible(!text.isEmpty());
|
|
|
|
|
m_binaryChooser->setCommandVersionArguments(QStringList(versionCommand));
|
|
|
|
|
|
2013-11-27 12:32:43 +01:00
|
|
|
setAbis(item.abiNames());
|
2013-10-25 13:47:08 +02:00
|
|
|
}
|
|
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
void DebuggerItemConfigWidget::apply()
|
2013-10-25 13:47:08 +02:00
|
|
|
{
|
2013-11-27 12:32:43 +01:00
|
|
|
DebuggerItem current = m_model->currentDebugger();
|
|
|
|
|
if (!current.isValid())
|
2013-10-29 11:53:11 +01:00
|
|
|
return; // Nothing was selected here.
|
2013-10-28 17:47:37 +01:00
|
|
|
|
2013-11-27 12:32:43 +01:00
|
|
|
store();
|
|
|
|
|
setItem(item());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerItemConfigWidget::commandWasChanged()
|
|
|
|
|
{
|
|
|
|
|
// Use DebuggerItemManager as a cache:
|
|
|
|
|
const DebuggerItem *existing
|
|
|
|
|
= DebuggerItemManager::findByCommand(m_binaryChooser->fileName());
|
|
|
|
|
if (existing) {
|
|
|
|
|
setAbis(existing->abiNames());
|
|
|
|
|
} else {
|
|
|
|
|
QFileInfo fi = QFileInfo(m_binaryChooser->path());
|
|
|
|
|
if (fi.isExecutable()) {
|
|
|
|
|
DebuggerItem tmp = item();
|
|
|
|
|
tmp.reinitializeFromFile();
|
|
|
|
|
setAbis(tmp.abiNames());
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-25 13:47:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
// DebuggerOptionsPage
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
DebuggerOptionsPage::DebuggerOptionsPage()
|
|
|
|
|
{
|
|
|
|
|
m_model = 0;
|
|
|
|
|
m_debuggerView = 0;
|
|
|
|
|
m_container = 0;
|
|
|
|
|
m_addButton = 0;
|
|
|
|
|
m_cloneButton = 0;
|
|
|
|
|
m_delButton = 0;
|
|
|
|
|
|
|
|
|
|
setId(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID);
|
|
|
|
|
setDisplayName(tr("Debuggers"));
|
|
|
|
|
setCategory(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY);
|
|
|
|
|
setDisplayCategory(QCoreApplication::translate("ProjectExplorer",
|
|
|
|
|
ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_TR_CATEGORY));
|
|
|
|
|
setCategoryIcon(QLatin1String(ProjectExplorer::Constants::PROJECTEXPLORER_SETTINGS_CATEGORY_ICON));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *DebuggerOptionsPage::createPage(QWidget *parent)
|
|
|
|
|
{
|
|
|
|
|
m_configWidget = new QWidget(parent);
|
|
|
|
|
|
|
|
|
|
m_addButton = new QPushButton(tr("Add"), m_configWidget);
|
|
|
|
|
m_cloneButton = new QPushButton(tr("Clone"), m_configWidget);
|
|
|
|
|
m_delButton = new QPushButton(tr("Remove"), m_configWidget);
|
|
|
|
|
|
|
|
|
|
m_container = new DetailsWidget(m_configWidget);
|
|
|
|
|
m_container->setState(DetailsWidget::NoSummary);
|
|
|
|
|
m_container->setVisible(false);
|
|
|
|
|
|
2013-10-28 14:05:12 +01:00
|
|
|
m_model = new DebuggerItemModel(parent);
|
2013-10-25 13:47:08 +02:00
|
|
|
|
|
|
|
|
m_debuggerView = new QTreeView(m_configWidget);
|
|
|
|
|
m_debuggerView->setModel(m_model);
|
|
|
|
|
m_debuggerView->setUniformRowHeights(true);
|
|
|
|
|
m_debuggerView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
|
m_debuggerView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
|
|
m_debuggerView->expandAll();
|
|
|
|
|
|
|
|
|
|
QHeaderView *header = m_debuggerView->header();
|
|
|
|
|
header->setStretchLastSection(false);
|
|
|
|
|
header->setResizeMode(0, QHeaderView::ResizeToContents);
|
|
|
|
|
header->setResizeMode(1, QHeaderView::ResizeToContents);
|
|
|
|
|
header->setResizeMode(2, QHeaderView::Stretch);
|
|
|
|
|
|
|
|
|
|
QVBoxLayout *buttonLayout = new QVBoxLayout();
|
|
|
|
|
buttonLayout->setSpacing(6);
|
|
|
|
|
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
buttonLayout->addWidget(m_addButton);
|
|
|
|
|
buttonLayout->addWidget(m_cloneButton);
|
|
|
|
|
buttonLayout->addWidget(m_delButton);
|
|
|
|
|
buttonLayout->addItem(new QSpacerItem(10, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
|
|
|
|
|
|
|
|
|
|
QVBoxLayout *verticalLayout = new QVBoxLayout();
|
|
|
|
|
verticalLayout->addWidget(m_debuggerView);
|
|
|
|
|
verticalLayout->addWidget(m_container);
|
|
|
|
|
|
|
|
|
|
QHBoxLayout *horizontalLayout = new QHBoxLayout(m_configWidget);
|
|
|
|
|
horizontalLayout->addLayout(verticalLayout);
|
|
|
|
|
horizontalLayout->addLayout(buttonLayout);
|
|
|
|
|
|
|
|
|
|
connect(m_debuggerView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
|
|
|
|
this, SLOT(debuggerSelectionChanged()));
|
|
|
|
|
|
|
|
|
|
connect(m_addButton, SIGNAL(clicked()), this, SLOT(addDebugger()), Qt::QueuedConnection);
|
|
|
|
|
connect(m_cloneButton, SIGNAL(clicked()), this, SLOT(cloneDebugger()), Qt::QueuedConnection);
|
|
|
|
|
connect(m_delButton, SIGNAL(clicked()), this, SLOT(removeDebugger()), Qt::QueuedConnection);
|
|
|
|
|
|
|
|
|
|
m_searchKeywords = tr("Debuggers");
|
|
|
|
|
|
2013-10-28 14:05:12 +01:00
|
|
|
m_itemConfigWidget = new DebuggerItemConfigWidget(m_model);
|
2013-10-25 13:47:08 +02:00
|
|
|
m_container->setWidget(m_itemConfigWidget);
|
|
|
|
|
|
|
|
|
|
updateState();
|
|
|
|
|
|
|
|
|
|
return m_configWidget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::apply()
|
|
|
|
|
{
|
2013-10-28 17:47:37 +01:00
|
|
|
m_itemConfigWidget->apply();
|
|
|
|
|
m_model->apply();
|
2013-10-25 13:47:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::cloneDebugger()
|
|
|
|
|
{
|
2013-10-28 17:47:37 +01:00
|
|
|
DebuggerItem item = m_model->currentDebugger();
|
|
|
|
|
if (!item.isValid())
|
|
|
|
|
return;
|
|
|
|
|
|
2013-10-25 13:47:08 +02:00
|
|
|
DebuggerItem newItem;
|
2013-11-12 12:01:48 +01:00
|
|
|
newItem.createId();
|
|
|
|
|
newItem.setAutoDetected(false);
|
2013-10-28 17:47:37 +01:00
|
|
|
newItem.setCommand(item.command());
|
|
|
|
|
newItem.setEngineType(item.engineType());
|
|
|
|
|
newItem.setAbis(item.abis());
|
|
|
|
|
newItem.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("Clone of %1").arg(item.displayName())));
|
2013-10-25 13:47:08 +02:00
|
|
|
newItem.setAutoDetected(false);
|
2013-10-28 17:47:37 +01:00
|
|
|
m_model->addDebugger(newItem);
|
2013-10-25 13:47:08 +02:00
|
|
|
m_debuggerView->setCurrentIndex(m_model->lastIndex());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::addDebugger()
|
|
|
|
|
{
|
|
|
|
|
DebuggerItem item;
|
2013-11-12 12:01:48 +01:00
|
|
|
item.createId();
|
|
|
|
|
item.setAutoDetected(false);
|
2013-10-25 13:47:08 +02:00
|
|
|
item.setEngineType(NoEngineType);
|
|
|
|
|
item.setDisplayName(DebuggerItemManager::uniqueDisplayName(tr("New Debugger")));
|
|
|
|
|
item.setAutoDetected(false);
|
2013-10-28 17:47:37 +01:00
|
|
|
m_model->addDebugger(item);
|
2013-10-25 13:47:08 +02:00
|
|
|
m_debuggerView->setCurrentIndex(m_model->lastIndex());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::removeDebugger()
|
|
|
|
|
{
|
2013-10-28 17:47:37 +01:00
|
|
|
QVariant id = m_model->currentDebuggerId();
|
|
|
|
|
m_model->removeDebugger(id);
|
2013-10-25 13:47:08 +02:00
|
|
|
m_debuggerView->setCurrentIndex(m_model->lastIndex());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::finish()
|
|
|
|
|
{
|
|
|
|
|
// Deleted by settingsdialog.
|
|
|
|
|
m_configWidget = 0;
|
|
|
|
|
|
|
|
|
|
// Children of m_configWidget.
|
|
|
|
|
m_container = 0;
|
|
|
|
|
m_debuggerView = 0;
|
|
|
|
|
m_addButton = 0;
|
|
|
|
|
m_cloneButton = 0;
|
|
|
|
|
m_delButton = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool DebuggerOptionsPage::matches(const QString &s) const
|
|
|
|
|
{
|
|
|
|
|
return m_searchKeywords.contains(s, Qt::CaseInsensitive);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::debuggerSelectionChanged()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_container, return);
|
|
|
|
|
|
|
|
|
|
QModelIndex mi = m_debuggerView->currentIndex();
|
|
|
|
|
mi = mi.sibling(mi.row(), 0);
|
|
|
|
|
m_model->setCurrentIndex(mi);
|
|
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
DebuggerItem item = m_model->currentDebugger();
|
|
|
|
|
|
|
|
|
|
m_itemConfigWidget->setItem(item);
|
|
|
|
|
m_container->setVisible(item.isValid());
|
2013-10-25 13:47:08 +02:00
|
|
|
updateState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::debuggerModelChanged()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_container, return);
|
|
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
QVariant id = m_model->currentDebuggerId();
|
|
|
|
|
const DebuggerItem *item = DebuggerItemManager::findById(id);
|
|
|
|
|
if (!item)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m_itemConfigWidget->setItem(*item);
|
|
|
|
|
m_container->setVisible(m_model->currentDebuggerId().isValid());
|
2013-10-25 13:47:08 +02:00
|
|
|
m_debuggerView->setCurrentIndex(m_model->currentIndex());
|
|
|
|
|
updateState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DebuggerOptionsPage::updateState()
|
|
|
|
|
{
|
|
|
|
|
if (!m_cloneButton)
|
|
|
|
|
return;
|
|
|
|
|
|
2013-10-28 17:47:37 +01:00
|
|
|
DebuggerItem item = m_model->currentDebugger();
|
|
|
|
|
|
2013-11-13 13:36:08 +01:00
|
|
|
bool canCopy = item.isValid() && item.canClone();
|
|
|
|
|
bool canDelete = m_model->currentIndex().parent().isValid() && !item.isAutoDetected();
|
2013-10-28 17:47:37 +01:00
|
|
|
|
2013-10-25 13:47:08 +02:00
|
|
|
m_cloneButton->setEnabled(canCopy);
|
|
|
|
|
m_delButton->setEnabled(canDelete);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Debugger
|