Commit 412a4b02 authored by con's avatar con
Browse files

Merge commit 'origin/1.1'

Conflicts:
	src/plugins/debugger/debuggeractions.cpp
	src/plugins/debugger/gdboptionpage.ui
parents 2a1c503b 6f85959d
......@@ -347,15 +347,6 @@
\bold{Build Settings} page. Qt Creator will run the make command using the
correct Qt version.
\note The \bold{Gdb Macros Build} step builds a small library along with your
project that is used for the custom display of Qt and STL objects in the
integrated debugger. The library is created and built in a "qtc-gdbmacros"
subfolder of your project's main directory, and loaded dynamically into your
application if you run it in the debugger. If the
debugging helper seems to break your build or your application, you can
remove the build step. You will still be able to debug applications, but the
contents of Qt and STL data types will not be displayed properly.
\section1 Dependencies
If you have multiple projects loaded in your session, you can configure
......@@ -1220,6 +1211,18 @@
registers. Both views are useful for low-level commands such as
\gui{Step Single Instruction} and \gui{Step Over Single Instruction}.
\section1 Debugging Helper Library
While debugging Qt Creator dynamically loads a helper library into
your program. This helper library enables Qt Creator to pretty print
Qt and STL types. The Qt SDK package already contains a prebuilt
debugging helper library. To create a debugging helper library
select the \{Options} from the \gui{Tools} menu, and go to the
\gui{Qt/Qt Versions} pane. As the internal layout of qt can
change between versions, the debugging helper library is build
per Qt Version.
\section1 A Walkthrough for the Debugger Frontend
In our \l{Writing a Simple Program with Qt Creator}{TextFinder} example, we
......@@ -1611,8 +1614,11 @@
\o Loading KDE4 designer plugins breaks the style in KDE < 4.2.1
due to a bug in KDE.
\o Scopes in \c{.pro} files are ignored, and environment variables not
expanded.
\o The DEFINES and INCLUDES set in \c{.pro} files are not dealt with
on a file-specific level. Because of this, handling of DEFINES has
been disabled completely. Also the \c{.qmake.cache} is not being
parsed. In general, the \c{.pro} file parser is incomplete and
problems are still to be expected.
\o Code completion for generated UI header files is updated only
after a build.
......
TEMPLATE = lib
CONFIG += shared
linux-* {
CONFIG -= release
CONFIG += debug
}
SOURCES=gdbmacros.cpp
......@@ -43,10 +43,12 @@ unix:!macx {
QMAKE_POST_LINK += $${QMAKE_COPY_FILE} $${COPYSRC} $${COPYDEST} $$SEPARATOR
}
target.files += $$OUT_PWD/$$DESTDIR/$$IDE_APP_WRAPPER
target.files += $$OUT_PWD/$$DESTDIR/$$IDE_APP_TARGET
wrapper.files = $$OUT_PWD/$$DESTDIR/$$IDE_APP_WRAPPER
wrapper.path = /bin
target.path = /bin
INSTALLS += target
INSTALLS += target wrapper
}
......
......@@ -75,6 +75,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const
setPage(CMakeRunPageId, new CMakeRunPage(this));
setStartId(startid);
setOption(QWizard::NoCancelButton);
setOption(QWizard::NoBackButtonOnStartPage);
}
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory,
......@@ -87,6 +89,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const
addPage(new CMakeRunPage(this, buildDirectory, false));
foreach(const QString &buildDirectory, needToUpdate)
addPage(new CMakeRunPage(this, buildDirectory, true));
setOption(QWizard::NoCancelButton);
setOption(QWizard::NoBackButtonOnStartPage);
}
CMakeManager *CMakeOpenProjectWizard::cmakeManager() const
......@@ -255,6 +259,9 @@ void CMakeRunPage::initWidgets()
m_output = new QPlainTextEdit(this);
m_output->setReadOnly(true);
QSizePolicy pl = m_output->sizePolicy();
pl.setVerticalStretch(1);
m_output->setSizePolicy(pl);
fl->addRow(m_output);
}
......
......@@ -512,7 +512,6 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader
cleanMakeStep->setValue("clean", true);
} else {
// We have a user file, but we could still be missing the cbp file
// TODO check that we have a cbp file and if not, open up a dialog ?
// or simply run createXml with the saved settings
QFileInfo sourceFileInfo(m_fileName);
QStringList needToCreate;
......
......@@ -155,7 +155,10 @@ QString CMakeManager::qtVersionForQMake(const QString &qmakePath)
return QString();
}
QString CMakeManager::findQtDir(const ProjectExplorer::Environment &env)
// this is mostly a copy from qt4versionmanager
// TODO refactor this code
// returns QPair< QTDIR, QT_INSTALL_DATA >
QPair<QString, QString> CMakeManager::findQtDir(const ProjectExplorer::Environment &env)
{
QStringList possibleCommands;
// On windows noone has renamed qmake, right?
......@@ -171,21 +174,23 @@ QString CMakeManager::findQtDir(const ProjectExplorer::Environment &env)
QFileInfo qmake(path + "/" + possibleCommand);
if (qmake.exists()) {
if (!qtVersionForQMake(qmake.absoluteFilePath()).isNull()) {
QDir qtDir = qmake.absoluteDir();
qtDir.cdUp();
QProcess proc;
proc.start(qmake.absoluteFilePath(), QStringList() << "-query" << "QT_INSTALL_DATA");
if (proc.waitForFinished()) {
return proc.readAll().trimmed();
return qMakePair(qtDir.absolutePath(), QString(proc.readAll().trimmed()));
} else {
proc.kill();
QDir dir(qmake.absoluteDir());
dir.cdUp();
return dir.absolutePath();
return qMakePair(qtDir.absolutePath(), dir.absolutePath());
}
}
}
}
}
return QString();
return qMakePair(QString(), QString());
}
// This code is more or less duplicated in qtversionmanager
......@@ -195,14 +200,16 @@ QString CMakeManager::findDumperLibrary(const ProjectExplorer::Environment &env)
static QString lastpath;
if (lastenv == env)
return lastpath;
QString qtdir = findQtDir(env);
if (qtdir.isEmpty())
QPair<QString, QString> pair = findQtDir(env);
QString qtInstallDataDir = pair.second;
if (qtInstallDataDir.isEmpty())
return QString();
uint hash = qHash(qtdir);
uint hash = qHash(pair.first);
QStringList directories;
directories
<< (qtdir + "/qtc-debugging-helper/")
<< (qtInstallDataDir + "/qtc-debugging-helper/")
<< (QApplication::applicationDirPath() + "/../qtc-debugging-helper/" + QString::number(hash)) + "/"
<< (QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/qtc-debugging-helper/" + QString::number(hash)) + "/";
foreach(const QString &directory, directories) {
......
......@@ -65,7 +65,7 @@ public:
static QString findDumperLibrary(const ProjectExplorer::Environment &env);
private:
static QString qtVersionForQMake(const QString &qmakePath);
static QString findQtDir(const ProjectExplorer::Environment &env);
static QPair<QString, QString> findQtDir(const ProjectExplorer::Environment &env);
int m_projectContext;
int m_projectLanguage;
CMakeSettingsPage *m_settingsPage;
......
......@@ -334,31 +334,41 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
m_d->m_splitAction = new QAction(tr("Split"), this);
cmd = am->registerAction(m_d->m_splitAction, Constants::SPLIT, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,2")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_splitAction, SIGNAL(triggered()), this, SLOT(split()));
m_d->m_splitSideBySideAction = new QAction(tr("Split Side by Side"), this);
cmd = am->registerAction(m_d->m_splitSideBySideAction, Constants::SPLIT_SIDE_BY_SIDE, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,3")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_splitSideBySideAction, SIGNAL(triggered()), this, SLOT(splitSideBySide()));
m_d->m_removeCurrentSplitAction = new QAction(tr("Remove Current Split"), this);
cmd = am->registerAction(m_d->m_removeCurrentSplitAction, Constants::REMOVE_CURRENT_SPLIT, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,0")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_removeCurrentSplitAction, SIGNAL(triggered()), this, SLOT(removeCurrentSplit()));
m_d->m_removeAllSplitsAction = new QAction(tr("Remove All Splits"), this);
cmd = am->registerAction(m_d->m_removeAllSplitsAction, Constants::REMOVE_ALL_SPLITS, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,1")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits()));
m_d->m_gotoOtherSplitAction = new QAction(tr("Goto Other Split"), this);
cmd = am->registerAction(m_d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,o")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit()));
......@@ -1538,6 +1548,7 @@ QByteArray EditorManager::saveState() const
bool EditorManager::restoreState(const QByteArray &state)
{
closeAllEditors(true);
removeAllSplits();
QDataStream stream(state);
QByteArray version;
......
......@@ -208,6 +208,8 @@ private slots:
void goBackInNavigationHistory();
void goForwardInNavigationHistory();
void makeCurrentEditorWritable();
public slots:
void split(Qt::Orientation orientation);
void split();
void splitSideBySide();
......
......@@ -158,7 +158,7 @@ DebuggerSettings *DebuggerSettings::instance()
instance->insertItem(UseDebuggingHelpers, item);
item->setDefaultValue(true);
item->setSettingsKey(debugModeGroup, QLatin1String("UseDebuggingHelper"));
item->setText(tr("Use Debugging Helper"));
item->setText(tr("Use debugging helper"));
item->setCheckable(true);
item->setDefaultValue(true);
......
......@@ -104,6 +104,7 @@ enum GdbCommandType
GdbQuerySources,
GdbAsyncOutput2,
GdbStart,
GdbExit,
GdbAttached,
GdbStubAttached,
GdbExecRun,
......@@ -743,6 +744,9 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
case GdbInfoThreads:
handleInfoThreads(record);
break;
case GdbExit:
handleExit(record);
break;
case GdbShowVersion:
handleShowVersion(record);
......@@ -1155,7 +1159,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
+ data.findChild("signal-name").toString();
}
q->showStatusMessage(msg);
sendCommand("-gdb-exit");
sendCommand("-gdb-exit", GdbExit);
return;
}
......@@ -1513,7 +1517,7 @@ void GdbEngine::exitDebugger()
sendCommand("detach");
else
sendCommand("kill");
sendCommand("-gdb-exit");
sendCommand("-gdb-exit", GdbExit);
// 20s can easily happen when loading webkit debug information
m_gdbProc.waitForFinished(20000);
if (m_gdbProc.state() != QProcess::Running) {
......@@ -1785,6 +1789,12 @@ void GdbEngine::handleAttach()
qq->reloadRegisters();
}
void GdbEngine::handleExit(const GdbResultRecord &response)
{
Q_UNUSED(response);
q->showStatusMessage(tr("Debugger exited."));
}
void GdbEngine::stepExec()
{
setTokenBarrier();
......@@ -2198,6 +2208,11 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
// within namespaces.
// Sometimes the path is relative too.
// 2 breakpoint keep y <MULTIPLE> 0x0040168e
// 2.1 y 0x0040168e in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
// 2.2 y 0x00401792 in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
// tested in ../../../tests/auto/debugger/
QRegExp re("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)");
re.setMinimal(true);
......@@ -2206,6 +2221,10 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
data->bpFuncName = re.cap(2).trimmed();
data->bpLineNumber = re.cap(4);
QString full = fullName(re.cap(3));
if (full.isEmpty()) {
qDebug() << "NO FULL NAME KNOWN FOR" << re.cap(3);
full = re.cap(3); // FIXME: wrong, but prevents recursion
}
data->markerLineNumber = data->bpLineNumber.toInt();
data->markerFileName = full;
data->bpFileName = full;
......@@ -3428,14 +3447,15 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record)
m_availableSimpleDebuggingHelpers.append(item.data());
if (m_availableSimpleDebuggingHelpers.isEmpty()) {
m_debuggingHelperState = DebuggingHelperUnavailable;
QMessageBox::warning(q->mainWindow(),
tr("Cannot find special data dumpers"),
tr("The debugged binary does not contain information needed for "
"nice display of Qt data types.\n\n"
"You might want to try including the file\n\n"
".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
"into your project directly.")
);
q->showStatusMessage(tr("Debugging helpers not found."));
//QMessageBox::warning(q->mainWindow(),
// tr("Cannot find special data dumpers"),
// tr("The debugged binary does not contain information needed for "
// "nice display of Qt data types.\n\n"
// "You might want to try including the file\n\n"
// ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
// "into your project directly.")
// );
} else {
m_debuggingHelperState = DebuggingHelperAvailable;
q->showStatusMessage(tr("%1 custom dumpers found.")
......
......@@ -200,6 +200,7 @@ private:
void handleQueryPwd(const GdbResultRecord &response);
void handleQuerySources(const GdbResultRecord &response);
void handleTargetCore(const GdbResultRecord &response);
void handleExit(const GdbResultRecord &response);
void debugMessage(const QString &msg);
QString dumperLibraryName() const;
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GdbOptionPage</class>
<widget class="QWidget" name="GdbOptionPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>429</width>
<height>452</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBoxLocations">
<property name="title">
<string>Gdb interaction</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="1">
<widget class="QLineEdit" name="environmentEdit"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelGdbLocation">
<property name="toolTip">
<string>This is either a full abolute path leading to the gdb binary you intend to use or the name of a gdb binary that will be searched in your PATH.</string>
</property>
<property name="text">
<string>Gdb location:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelEnvironment">
<property name="text">
<string>Environment:</string>
</property>
<property name="buddy">
<cstring>environmentEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelGdbStartupScript">
<property name="toolTip">
<string>This is either empty or points to a file containing gdb commands that will be executed immediately after gdb starts up.</string>
</property>
<property name="text">
<string>Gdb startup script:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Core::Utils::PathChooser" name="scriptFileChooser" native="true"/>
</item>
<item row="0" column="1">
<widget class="Core::Utils::PathChooser" name="gdbLocationChooser" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxPluginDebugging">
<property name="title">
<string>Behaviour of breakpoint setting in plugins</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="radioButtonAllPluginBreakpoints">
<property name="toolTip">
<string>This is the slowest but safest option.</string>
</property>
<property name="text">
<string>Try to set breakpoints in plugins always automatically.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioButtonSelectedPluginBreakpoints">
<property name="text">
<string>Try to set breakpoints in selected plugins</string>
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelSelectedPluginBreakpoints">
<property name="text">
<string>Matching regular expression: </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEditSelectedPluginBreakpointsPattern"/>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="radioButtonNoPluginBreakpoints">
<property name="text">
<string>Never set breakpoints in plugins automatically</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>User interface</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="checkBoxListSourceFiles">
<property name="toolTip">
<string>Checking this will populate the source file view automatically but might slow down debugger startup considerably.</string>
</property>
<property name="text">
<string>Populate source file view automatically</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxSkipKnownFrames">
<property name="toolTip">
<string>When this option is checked, 'Step Into' compresses several steps into one in certain situations, leading to 'less noisy' debugging. So will, e.g., the atomic
reference counting code be skipped, and a single 'Step Into' for a signal emission will end up directly in the slot connected to it.</string>
</property>
<property name="text">
<string>Skip known frames when stepping</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxUseToolTips">
<property name="toolTip">
<string>Checking this will make enable tooltips for variable values during debugging. Since this can slow down debugging and does not provide reliable information as it does not use scope information, it is switched off by default.</string>
</property>
<property name="text">
<string>Use tooltips while debugging</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelMaximalStackDepth">
<property name="text">
<string>Maximal stack depth:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxMaximalStackDepth">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="specialValueText">
<string>&lt;unlimited&gt;</string>
</property>
<property name="maximum">
<number>999</number>
</property>
<property name="singleStep">
<number>5</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Core::Utils::PathChooser</class>
<extends>QWidget</extends>
<header location="global">utils/pathchooser.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
......@@ -932,7 +932,6 @@ QString WatchHandler::watcherName(const QString &exp)
void WatchHandler::watchExpression(const QString &exp)
{
// FIXME: 'exp' can contain illegal characters
//MODEL_DEBUG("WATCH: " << exp);
m_watchers[exp] = watcherCounter++;
WatchData data;
data.exp = exp;
......
......@@ -96,7 +96,7 @@ public:
} else if (index.column() == 0) {
// the watcher name column
theDebuggerAction(RemoveWatchExpression)->trigger(exp);
theDebuggerAction(WatchExpression)->trigger(lineEdit->text());
theDebuggerAction(WatchExpression)->trigger(value);
}
}
......@@ -175,8 +175,6 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QModelIndex idx = indexAt(ev->pos());