Merge commit 'origin/1.1'

Conflicts:
	src/plugins/debugger/debuggeractions.cpp
	src/plugins/debugger/gdboptionpage.ui
This commit is contained in:
con
2009-04-17 15:17:31 +02:00
24 changed files with 657 additions and 186 deletions

View File

@@ -347,15 +347,6 @@
\bold{Build Settings} page. Qt Creator will run the make command using the \bold{Build Settings} page. Qt Creator will run the make command using the
correct Qt version. 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 \section1 Dependencies
If you have multiple projects loaded in your session, you can configure 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 registers. Both views are useful for low-level commands such as
\gui{Step Single Instruction} and \gui{Step Over Single Instruction}. \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 \section1 A Walkthrough for the Debugger Frontend
In our \l{Writing a Simple Program with Qt Creator}{TextFinder} example, we 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 \o Loading KDE4 designer plugins breaks the style in KDE < 4.2.1
due to a bug in KDE. due to a bug in KDE.
\o Scopes in \c{.pro} files are ignored, and environment variables not \o The DEFINES and INCLUDES set in \c{.pro} files are not dealt with
expanded. 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 \o Code completion for generated UI header files is updated only
after a build. after a build.

View File

@@ -1,3 +1,7 @@
TEMPLATE = lib TEMPLATE = lib
CONFIG += shared CONFIG += shared
linux-* {
CONFIG -= release
CONFIG += debug
}
SOURCES=gdbmacros.cpp SOURCES=gdbmacros.cpp

View File

@@ -43,10 +43,12 @@ unix:!macx {
QMAKE_POST_LINK += $${QMAKE_COPY_FILE} $${COPYSRC} $${COPYDEST} $$SEPARATOR QMAKE_POST_LINK += $${QMAKE_COPY_FILE} $${COPYSRC} $${COPYDEST} $$SEPARATOR
} }
target.files += $$OUT_PWD/$$DESTDIR/$$IDE_APP_WRAPPER wrapper.files = $$OUT_PWD/$$DESTDIR/$$IDE_APP_WRAPPER
target.files += $$OUT_PWD/$$DESTDIR/$$IDE_APP_TARGET wrapper.path = /bin
target.path = /bin target.path = /bin
INSTALLS += target
INSTALLS += target wrapper
} }

View File

@@ -75,6 +75,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const
setPage(CMakeRunPageId, new CMakeRunPage(this)); setPage(CMakeRunPageId, new CMakeRunPage(this));
setStartId(startid); setStartId(startid);
setOption(QWizard::NoCancelButton);
setOption(QWizard::NoBackButtonOnStartPage);
} }
CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory, CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const QString &sourceDirectory,
@@ -87,6 +89,8 @@ CMakeOpenProjectWizard::CMakeOpenProjectWizard(CMakeManager *cmakeManager, const
addPage(new CMakeRunPage(this, buildDirectory, false)); addPage(new CMakeRunPage(this, buildDirectory, false));
foreach(const QString &buildDirectory, needToUpdate) foreach(const QString &buildDirectory, needToUpdate)
addPage(new CMakeRunPage(this, buildDirectory, true)); addPage(new CMakeRunPage(this, buildDirectory, true));
setOption(QWizard::NoCancelButton);
setOption(QWizard::NoBackButtonOnStartPage);
} }
CMakeManager *CMakeOpenProjectWizard::cmakeManager() const CMakeManager *CMakeOpenProjectWizard::cmakeManager() const
@@ -255,6 +259,9 @@ void CMakeRunPage::initWidgets()
m_output = new QPlainTextEdit(this); m_output = new QPlainTextEdit(this);
m_output->setReadOnly(true); m_output->setReadOnly(true);
QSizePolicy pl = m_output->sizePolicy();
pl.setVerticalStretch(1);
m_output->setSizePolicy(pl);
fl->addRow(m_output); fl->addRow(m_output);
} }

View File

@@ -512,7 +512,6 @@ void CMakeProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader
cleanMakeStep->setValue("clean", true); cleanMakeStep->setValue("clean", true);
} else { } else {
// We have a user file, but we could still be missing the cbp file // 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 // or simply run createXml with the saved settings
QFileInfo sourceFileInfo(m_fileName); QFileInfo sourceFileInfo(m_fileName);
QStringList needToCreate; QStringList needToCreate;

View File

@@ -155,7 +155,10 @@ QString CMakeManager::qtVersionForQMake(const QString &qmakePath)
return QString(); 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; QStringList possibleCommands;
// On windows noone has renamed qmake, right? // On windows noone has renamed qmake, right?
@@ -171,21 +174,23 @@ QString CMakeManager::findQtDir(const ProjectExplorer::Environment &env)
QFileInfo qmake(path + "/" + possibleCommand); QFileInfo qmake(path + "/" + possibleCommand);
if (qmake.exists()) { if (qmake.exists()) {
if (!qtVersionForQMake(qmake.absoluteFilePath()).isNull()) { if (!qtVersionForQMake(qmake.absoluteFilePath()).isNull()) {
QDir qtDir = qmake.absoluteDir();
qtDir.cdUp();
QProcess proc; QProcess proc;
proc.start(qmake.absoluteFilePath(), QStringList() << "-query" << "QT_INSTALL_DATA"); proc.start(qmake.absoluteFilePath(), QStringList() << "-query" << "QT_INSTALL_DATA");
if (proc.waitForFinished()) { if (proc.waitForFinished()) {
return proc.readAll().trimmed(); return qMakePair(qtDir.absolutePath(), QString(proc.readAll().trimmed()));
} else { } else {
proc.kill(); proc.kill();
QDir dir(qmake.absoluteDir()); QDir dir(qmake.absoluteDir());
dir.cdUp(); 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 // This code is more or less duplicated in qtversionmanager
@@ -195,14 +200,16 @@ QString CMakeManager::findDumperLibrary(const ProjectExplorer::Environment &env)
static QString lastpath; static QString lastpath;
if (lastenv == env) if (lastenv == env)
return lastpath; return lastpath;
QString qtdir = findQtDir(env);
if (qtdir.isEmpty()) QPair<QString, QString> pair = findQtDir(env);
QString qtInstallDataDir = pair.second;
if (qtInstallDataDir.isEmpty())
return QString(); return QString();
uint hash = qHash(qtdir); uint hash = qHash(pair.first);
QStringList directories; QStringList directories;
directories directories
<< (qtdir + "/qtc-debugging-helper/") << (qtInstallDataDir + "/qtc-debugging-helper/")
<< (QApplication::applicationDirPath() + "/../qtc-debugging-helper/" + QString::number(hash)) + "/" << (QApplication::applicationDirPath() + "/../qtc-debugging-helper/" + QString::number(hash)) + "/"
<< (QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/qtc-debugging-helper/" + QString::number(hash)) + "/"; << (QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/qtc-debugging-helper/" + QString::number(hash)) + "/";
foreach(const QString &directory, directories) { foreach(const QString &directory, directories) {

View File

@@ -65,7 +65,7 @@ public:
static QString findDumperLibrary(const ProjectExplorer::Environment &env); static QString findDumperLibrary(const ProjectExplorer::Environment &env);
private: private:
static QString qtVersionForQMake(const QString &qmakePath); 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_projectContext;
int m_projectLanguage; int m_projectLanguage;
CMakeSettingsPage *m_settingsPage; CMakeSettingsPage *m_settingsPage;

View File

@@ -334,31 +334,41 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) :
m_d->m_splitAction = new QAction(tr("Split"), this); m_d->m_splitAction = new QAction(tr("Split"), this);
cmd = am->registerAction(m_d->m_splitAction, Constants::SPLIT, editManagerContext); cmd = am->registerAction(m_d->m_splitAction, Constants::SPLIT, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,2"))); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,2")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_splitAction, SIGNAL(triggered()), this, SLOT(split())); connect(m_d->m_splitAction, SIGNAL(triggered()), this, SLOT(split()));
m_d->m_splitSideBySideAction = new QAction(tr("Split Side by Side"), this); 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); cmd = am->registerAction(m_d->m_splitSideBySideAction, Constants::SPLIT_SIDE_BY_SIDE, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,3"))); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,3")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_splitSideBySideAction, SIGNAL(triggered()), this, SLOT(splitSideBySide())); connect(m_d->m_splitSideBySideAction, SIGNAL(triggered()), this, SLOT(splitSideBySide()));
m_d->m_removeCurrentSplitAction = new QAction(tr("Remove Current Split"), this); m_d->m_removeCurrentSplitAction = new QAction(tr("Remove Current Split"), this);
cmd = am->registerAction(m_d->m_removeCurrentSplitAction, Constants::REMOVE_CURRENT_SPLIT, editManagerContext); cmd = am->registerAction(m_d->m_removeCurrentSplitAction, Constants::REMOVE_CURRENT_SPLIT, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,0"))); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,0")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_removeCurrentSplitAction, SIGNAL(triggered()), this, SLOT(removeCurrentSplit())); connect(m_d->m_removeCurrentSplitAction, SIGNAL(triggered()), this, SLOT(removeCurrentSplit()));
m_d->m_removeAllSplitsAction = new QAction(tr("Remove All Splits"), this); m_d->m_removeAllSplitsAction = new QAction(tr("Remove All Splits"), this);
cmd = am->registerAction(m_d->m_removeAllSplitsAction, Constants::REMOVE_ALL_SPLITS, editManagerContext); cmd = am->registerAction(m_d->m_removeAllSplitsAction, Constants::REMOVE_ALL_SPLITS, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,1"))); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,1")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits())); connect(m_d->m_removeAllSplitsAction, SIGNAL(triggered()), this, SLOT(removeAllSplits()));
m_d->m_gotoOtherSplitAction = new QAction(tr("Goto Other Split"), this); m_d->m_gotoOtherSplitAction = new QAction(tr("Goto Other Split"), this);
cmd = am->registerAction(m_d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext); cmd = am->registerAction(m_d->m_gotoOtherSplitAction, Constants::GOTO_OTHER_SPLIT, editManagerContext);
#ifndef Q_OS_MAC
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,o"))); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E,o")));
#endif
mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT); mwindow->addAction(cmd, Constants::G_WINDOW_SPLIT);
connect(m_d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit())); connect(m_d->m_gotoOtherSplitAction, SIGNAL(triggered()), this, SLOT(gotoOtherSplit()));
@@ -1538,6 +1548,7 @@ QByteArray EditorManager::saveState() const
bool EditorManager::restoreState(const QByteArray &state) bool EditorManager::restoreState(const QByteArray &state)
{ {
closeAllEditors(true); closeAllEditors(true);
removeAllSplits();
QDataStream stream(state); QDataStream stream(state);
QByteArray version; QByteArray version;

View File

@@ -208,6 +208,8 @@ private slots:
void goBackInNavigationHistory(); void goBackInNavigationHistory();
void goForwardInNavigationHistory(); void goForwardInNavigationHistory();
void makeCurrentEditorWritable(); void makeCurrentEditorWritable();
public slots:
void split(Qt::Orientation orientation); void split(Qt::Orientation orientation);
void split(); void split();
void splitSideBySide(); void splitSideBySide();

View File

@@ -158,7 +158,7 @@ DebuggerSettings *DebuggerSettings::instance()
instance->insertItem(UseDebuggingHelpers, item); instance->insertItem(UseDebuggingHelpers, item);
item->setDefaultValue(true); item->setDefaultValue(true);
item->setSettingsKey(debugModeGroup, QLatin1String("UseDebuggingHelper")); item->setSettingsKey(debugModeGroup, QLatin1String("UseDebuggingHelper"));
item->setText(tr("Use Debugging Helper")); item->setText(tr("Use debugging helper"));
item->setCheckable(true); item->setCheckable(true);
item->setDefaultValue(true); item->setDefaultValue(true);

View File

@@ -104,6 +104,7 @@ enum GdbCommandType
GdbQuerySources, GdbQuerySources,
GdbAsyncOutput2, GdbAsyncOutput2,
GdbStart, GdbStart,
GdbExit,
GdbAttached, GdbAttached,
GdbStubAttached, GdbStubAttached,
GdbExecRun, GdbExecRun,
@@ -743,6 +744,9 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
case GdbInfoThreads: case GdbInfoThreads:
handleInfoThreads(record); handleInfoThreads(record);
break; break;
case GdbExit:
handleExit(record);
break;
case GdbShowVersion: case GdbShowVersion:
handleShowVersion(record); handleShowVersion(record);
@@ -1155,7 +1159,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
+ data.findChild("signal-name").toString(); + data.findChild("signal-name").toString();
} }
q->showStatusMessage(msg); q->showStatusMessage(msg);
sendCommand("-gdb-exit"); sendCommand("-gdb-exit", GdbExit);
return; return;
} }
@@ -1513,7 +1517,7 @@ void GdbEngine::exitDebugger()
sendCommand("detach"); sendCommand("detach");
else else
sendCommand("kill"); sendCommand("kill");
sendCommand("-gdb-exit"); sendCommand("-gdb-exit", GdbExit);
// 20s can easily happen when loading webkit debug information // 20s can easily happen when loading webkit debug information
m_gdbProc.waitForFinished(20000); m_gdbProc.waitForFinished(20000);
if (m_gdbProc.state() != QProcess::Running) { if (m_gdbProc.state() != QProcess::Running) {
@@ -1785,6 +1789,12 @@ void GdbEngine::handleAttach()
qq->reloadRegisters(); qq->reloadRegisters();
} }
void GdbEngine::handleExit(const GdbResultRecord &response)
{
Q_UNUSED(response);
q->showStatusMessage(tr("Debugger exited."));
}
void GdbEngine::stepExec() void GdbEngine::stepExec()
{ {
setTokenBarrier(); setTokenBarrier();
@@ -2198,6 +2208,11 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
// within namespaces. // within namespaces.
// Sometimes the path is relative too. // 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]|$)"); QRegExp re("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)");
re.setMinimal(true); re.setMinimal(true);
@@ -2206,6 +2221,10 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData *
data->bpFuncName = re.cap(2).trimmed(); data->bpFuncName = re.cap(2).trimmed();
data->bpLineNumber = re.cap(4); data->bpLineNumber = re.cap(4);
QString full = fullName(re.cap(3)); 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->markerLineNumber = data->bpLineNumber.toInt();
data->markerFileName = full; data->markerFileName = full;
data->bpFileName = full; data->bpFileName = full;
@@ -3428,14 +3447,15 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record)
m_availableSimpleDebuggingHelpers.append(item.data()); m_availableSimpleDebuggingHelpers.append(item.data());
if (m_availableSimpleDebuggingHelpers.isEmpty()) { if (m_availableSimpleDebuggingHelpers.isEmpty()) {
m_debuggingHelperState = DebuggingHelperUnavailable; m_debuggingHelperState = DebuggingHelperUnavailable;
QMessageBox::warning(q->mainWindow(), q->showStatusMessage(tr("Debugging helpers not found."));
tr("Cannot find special data dumpers"), //QMessageBox::warning(q->mainWindow(),
tr("The debugged binary does not contain information needed for " // tr("Cannot find special data dumpers"),
"nice display of Qt data types.\n\n" // tr("The debugged binary does not contain information needed for "
"You might want to try including the file\n\n" // "nice display of Qt data types.\n\n"
".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n" // "You might want to try including the file\n\n"
"into your project directly.") // ".../share/qtcreator/gdbmacros/gdbmacros.cpp\n\n"
); // "into your project directly.")
// );
} else { } else {
m_debuggingHelperState = DebuggingHelperAvailable; m_debuggingHelperState = DebuggingHelperAvailable;
q->showStatusMessage(tr("%1 custom dumpers found.") q->showStatusMessage(tr("%1 custom dumpers found.")

View File

@@ -200,6 +200,7 @@ private:
void handleQueryPwd(const GdbResultRecord &response); void handleQueryPwd(const GdbResultRecord &response);
void handleQuerySources(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response);
void handleTargetCore(const GdbResultRecord &response); void handleTargetCore(const GdbResultRecord &response);
void handleExit(const GdbResultRecord &response);
void debugMessage(const QString &msg); void debugMessage(const QString &msg);
QString dumperLibraryName() const; QString dumperLibraryName() const;

View File

@@ -0,0 +1,232 @@
<?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>

View File

@@ -932,7 +932,6 @@ QString WatchHandler::watcherName(const QString &exp)
void WatchHandler::watchExpression(const QString &exp) void WatchHandler::watchExpression(const QString &exp)
{ {
// FIXME: 'exp' can contain illegal characters // FIXME: 'exp' can contain illegal characters
//MODEL_DEBUG("WATCH: " << exp);
m_watchers[exp] = watcherCounter++; m_watchers[exp] = watcherCounter++;
WatchData data; WatchData data;
data.exp = exp; data.exp = exp;

View File

@@ -96,7 +96,7 @@ public:
} else if (index.column() == 0) { } else if (index.column() == 0) {
// the watcher name column // the watcher name column
theDebuggerAction(RemoveWatchExpression)->trigger(exp); 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()); QModelIndex idx = indexAt(ev->pos());
QModelIndex mi0 = idx.sibling(idx.row(), 0); QModelIndex mi0 = idx.sibling(idx.row(), 0);
QString exp = model()->data(mi0).toString(); QString exp = model()->data(mi0).toString();
QModelIndex mi1 = idx.sibling(idx.row(), 0);
QString value = model()->data(mi1).toString();
menu.addSeparator(); menu.addSeparator();
int type = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression; int type = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression;

View File

@@ -0,0 +1,14 @@
fakevim is based on eventFilters installed on a QTextEdit or a QPlainTextEdit.
It basically catches all keystrokes and modifies some internal state that
make the resulting text in the editor look like it was using vim.
There are only a few files in here:
fakevimplugin.{h,cpp} - interaction with the rest of Creator
fakevimactions.{h,cpp} - settings
fakevimhandler.{h,cpp} - the "real" event
There are some more hints for developers in fakevimhandler.cpp

View File

@@ -29,13 +29,18 @@
#include "fakevimhandler.h" #include "fakevimhandler.h"
// Please do not add any direct dependencies to other Qt Creator code here. //
// ATTENTION:
//
// 1 Please do not add any direct dependencies to other Qt Creator code here.
// Instead emit signals and let the FakeVimPlugin channel the information to // Instead emit signals and let the FakeVimPlugin channel the information to
// Qt Creator. The idea is to keep this file here in a "clean" state that // Qt Creator. The idea is to keep this file here in a "clean" state that
// allows easy reuse with any QTextEdit or QPlainTextEdit derived class. // allows easy reuse with any QTextEdit or QPlainTextEdit derived class.
//
// 2 There are a few auto tests located in ../../../tests/auto/fakevim.
// Some conventions: // Commands that are covered there are marked as "// tested" below.
//
// 3 Some conventions:
// //
// Use 1 based line numbers and 0 based column numbers. Even though // Use 1 based line numbers and 0 based column numbers. Even though
// the 1 based line are not nice it matches vim's and QTextEdit's 'line' // the 1 based line are not nice it matches vim's and QTextEdit's 'line'
@@ -47,10 +52,10 @@
// There is always a "current" cursor (m_tc). A current "region of interest" // There is always a "current" cursor (m_tc). A current "region of interest"
// spans between m_anchor (== anchor()) and m_tc.position() (== position()) // spans between m_anchor (== anchor()) and m_tc.position() (== position())
// The value of m_tc.anchor() is not used. // The value of m_tc.anchor() is not used.
//
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QObject> #include <QtCore/QObject>
@@ -277,7 +282,7 @@ public:
// to reduce line noise // to reduce line noise
void moveToEndOfDocument() { m_tc.movePosition(EndOfDocument, MoveAnchor); } void moveToEndOfDocument() { m_tc.movePosition(EndOfDocument, MoveAnchor); }
void moveToStartOfLine() { m_tc.movePosition(StartOfLine, MoveAnchor); } void moveToStartOfLine();
void moveToEndOfLine(); void moveToEndOfLine();
void moveUp(int n = 1) { moveDown(-n); } void moveUp(int n = 1) { moveDown(-n); }
void moveDown(int n = 1); // { m_tc.movePosition(Down, MoveAnchor, n); } void moveDown(int n = 1); // { m_tc.movePosition(Down, MoveAnchor, n); }
@@ -352,6 +357,8 @@ public:
// extra data for '.' // extra data for '.'
void replay(const QString &text, int count); void replay(const QString &text, int count);
void setDotCommand(const QString &cmd) { m_dotCommand = cmd; }
void setDotCommand(const QString &cmd, int n) { m_dotCommand = cmd.arg(n); }
QString m_dotCommand; QString m_dotCommand;
bool m_inReplay; // true if we are executing a '.' bool m_inReplay; // true if we are executing a '.'
@@ -612,8 +619,9 @@ void FakeVimHandler::Private::moveDown(int n)
m_tc.movePosition(Down, MoveAnchor, n); m_tc.movePosition(Down, MoveAnchor, n);
#else #else
const int col = m_tc.position() - m_tc.block().position(); const int col = m_tc.position() - m_tc.block().position();
const int line = m_tc.block().blockNumber(); const int lastLine = m_tc.document()->lastBlock().blockNumber();
const QTextBlock &block = m_tc.document()->findBlockByNumber(line + n); const int targetLine = qMax(0, qMin(lastLine, m_tc.block().blockNumber() + n));
const QTextBlock &block = m_tc.document()->findBlockByNumber(targetLine);
const int pos = block.position(); const int pos = block.position();
setPosition(pos + qMin(block.length() - 1, col)); setPosition(pos + qMin(block.length() - 1, col));
moveToTargetColumn(); moveToTargetColumn();
@@ -631,6 +639,17 @@ void FakeVimHandler::Private::moveToEndOfLine()
#endif #endif
} }
void FakeVimHandler::Private::moveToStartOfLine()
{
#if 0
// does not work for "hidden" documents like in the autotests
m_tc.movePosition(StartOfLine, MoveAnchor);
#else
const QTextBlock &block = m_tc.block();
setPosition(block.position());
#endif
}
void FakeVimHandler::Private::finishMovement(const QString &dotCommand) void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
{ {
//qDebug() << "ANCHOR: " << position() << anchor(); //qDebug() << "ANCHOR: " << position() << anchor();
@@ -655,7 +674,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
if (anchor() >= position()) if (anchor() >= position())
m_anchor++; m_anchor++;
if (!dotCommand.isEmpty()) if (!dotCommand.isEmpty())
m_dotCommand = "c" + dotCommand; setDotCommand("c" + dotCommand);
QString text = removeSelectedText(); QString text = removeSelectedText();
//qDebug() << "CHANGING TO INSERT MODE" << text; //qDebug() << "CHANGING TO INSERT MODE" << text;
m_registers[m_register] = text; m_registers[m_register] = text;
@@ -667,7 +686,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
if (anchor() >= position()) if (anchor() >= position())
m_anchor++; m_anchor++;
if (!dotCommand.isEmpty()) if (!dotCommand.isEmpty())
m_dotCommand = "d" + dotCommand; setDotCommand("d" + dotCommand);
m_registers[m_register] = removeSelectedText(); m_registers[m_register] = removeSelectedText();
m_submode = NoSubMode; m_submode = NoSubMode;
if (atEndOfLine()) if (atEndOfLine())
@@ -693,8 +712,6 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
updateMiniBuffer(); updateMiniBuffer();
} }
moveToTargetColumn();
m_moveType = MoveInclusive; m_moveType = MoveInclusive;
m_mvcount.clear(); m_mvcount.clear();
m_opcount.clear(); m_opcount.clear();
@@ -846,13 +863,19 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
} else if (m_submode == RegisterSubMode) { } else if (m_submode == RegisterSubMode) {
m_register = key; m_register = key;
m_submode = NoSubMode; m_submode = NoSubMode;
} else if (m_submode == ChangeSubMode && key == 'c') { } else if (m_submode == ChangeSubMode && key == 'c') { // tested
moveToStartOfLine(); moveDown(count() - 1);
moveToEndOfLine();
moveLeft();
setAnchor(); setAnchor();
moveDown(count()); moveToStartOfLine();
setTargetColumn();
moveUp(count() - 1);
m_moveType = MoveLineWise; m_moveType = MoveLineWise;
finishMovement("c"); m_lastInsertion.clear();
} else if (m_submode == DeleteSubMode && key == 'd') { setDotCommand("%1cc", count());
finishMovement();
} else if (m_submode == DeleteSubMode && key == 'd') { // tested
moveToStartOfLine(); moveToStartOfLine();
setAnchor(); setAnchor();
moveDown(count()); moveDown(count());
@@ -868,19 +891,19 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setAnchor(); setAnchor();
moveDown(count() - 1); moveDown(count() - 1);
m_moveType = MoveLineWise; m_moveType = MoveLineWise;
m_dotCommand = QString("%1<<").arg(count()); setDotCommand("%1<<", count());
finishMovement(); finishMovement();
} else if (m_submode == ShiftRightSubMode && key == '>') { } else if (m_submode == ShiftRightSubMode && key == '>') {
setAnchor(); setAnchor();
moveDown(count() - 1); moveDown(count() - 1);
m_moveType = MoveLineWise; m_moveType = MoveLineWise;
m_dotCommand = QString("%1>>").arg(count()); setDotCommand("%1>>", count());
finishMovement(); finishMovement();
} else if (m_submode == IndentSubMode && key == '=') { } else if (m_submode == IndentSubMode && key == '=') {
setAnchor(); setAnchor();
moveDown(count() - 1); moveDown(count() - 1);
m_moveType = MoveLineWise; m_moveType = MoveLineWise;
m_dotCommand = QString("%1>>").arg(count()); setDotCommand("%1>>", count());
finishMovement(); finishMovement();
} else if (m_submode == ZSubMode) { } else if (m_submode == ZSubMode) {
//qDebug() << "Z_MODE " << cursorLineInDocument() << linesOnScreen(); //qDebug() << "Z_MODE " << cursorLineInDocument() << linesOnScreen();
@@ -927,7 +950,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
m_tc.insertText(QString(count(), text.at(0))); m_tc.insertText(QString(count(), text.at(0)));
m_moveType = MoveExclusive; m_moveType = MoveExclusive;
m_submode = NoSubMode; m_submode = NoSubMode;
m_dotCommand = QString("%1r%2").arg(count()).arg(text); setDotCommand("%1r" + text, count());
finishMovement(); finishMovement();
} else { } else {
m_submode = NoSubMode; m_submode = NoSubMode;
@@ -1072,6 +1095,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
m_mode = InsertMode; m_mode = InsertMode;
moveToEndOfLine(); moveToEndOfLine();
m_lastInsertion.clear(); m_lastInsertion.clear();
} else if (key == control('a')) {
// FIXME: eat it to prevent the global "select all" shortcut to trigger
} else if (key == 'b') { } else if (key == 'b') {
m_moveType = MoveExclusive; m_moveType = MoveExclusive;
moveToWordBoundary(false, false); moveToWordBoundary(false, false);
@@ -1124,7 +1149,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
handleStartOfLine(); handleStartOfLine();
scrollToLineInDocument(cursorLineInDocument() - sline); scrollToLineInDocument(cursorLineInDocument() - sline);
finishMovement(); finishMovement();
} else if (key == 'e') { } else if (key == 'e') { // tested
m_moveType = MoveInclusive; m_moveType = MoveInclusive;
moveToWordBoundary(false, true); moveToWordBoundary(false, true);
finishMovement(); finishMovement();
@@ -1174,13 +1199,13 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
handleStartOfLine(); handleStartOfLine();
finishMovement(); finishMovement();
} else if (key == 'i') { } else if (key == 'i') {
m_dotCommand = "i"; //QString("%1i").arg(count()); setDotCommand("i"); // setDotCommand("%1i", count());
enterInsertMode(); enterInsertMode();
updateMiniBuffer(); updateMiniBuffer();
if (atEndOfLine()) if (atEndOfLine())
moveLeft(); moveLeft();
} else if (key == 'I') { } else if (key == 'I') {
m_dotCommand = "I"; //QString("%1I").arg(count()); setDotCommand("I"); // setDotCommand("%1I", count());
enterInsertMode(); enterInsertMode();
if (m_gflag) if (m_gflag)
moveToStartOfLine(); moveToStartOfLine();
@@ -1255,7 +1280,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
search(lastSearchString(), !m_lastSearchForward); search(lastSearchString(), !m_lastSearchForward);
recordJump(); recordJump();
} else if (key == 'o' || key == 'O') { } else if (key == 'o' || key == 'O') {
m_dotCommand = QString("%1o").arg(count()); setDotCommand("%1o", count());
enterInsertMode(); enterInsertMode();
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
if (key == 'O') if (key == 'O')
@@ -1292,18 +1317,18 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
moveLeft(); moveLeft();
} }
} }
m_dotCommand = QString("%1p").arg(count()); setDotCommand("%1p", count());
finishMovement(); finishMovement();
} else if (key == 'r') { } else if (key == 'r') {
m_submode = ReplaceSubMode; m_submode = ReplaceSubMode;
m_dotCommand = "r"; setDotCommand("r");
} else if (key == 'R') { } else if (key == 'R') {
// FIXME: right now we repeat the insertion count() times, // FIXME: right now we repeat the insertion count() times,
// but not the deletion // but not the deletion
m_lastInsertion.clear(); m_lastInsertion.clear();
m_mode = InsertMode; m_mode = InsertMode;
m_submode = ReplaceSubMode; m_submode = ReplaceSubMode;
m_dotCommand = "R"; setDotCommand("R");
} else if (key == control('r')) { } else if (key == control('r')) {
redo(); redo();
} else if (key == 's') { } else if (key == 's') {
@@ -1312,7 +1337,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setAnchor(); setAnchor();
moveRight(qMin(count(), rightDist())); moveRight(qMin(count(), rightDist()));
m_registers[m_register] = removeSelectedText(); m_registers[m_register] = removeSelectedText();
m_dotCommand = "s"; //QString("%1s").arg(count()); setDotCommand("s"); // setDotCommand("%1s", count());
m_opcount.clear(); m_opcount.clear();
m_mvcount.clear(); m_mvcount.clear();
enterInsertMode(); enterInsertMode();
@@ -1339,7 +1364,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
enterVisualMode(VisualLineMode); enterVisualMode(VisualLineMode);
} else if (key == control('v')) { } else if (key == control('v')) {
enterVisualMode(VisualBlockMode); enterVisualMode(VisualBlockMode);
} else if (key == 'w') { } else if (key == 'w') { // tested
// Special case: "cw" and "cW" work the same as "ce" and "cE" if the // Special case: "cw" and "cW" work the same as "ce" and "cE" if the
// cursor is on a non-blank. // cursor is on a non-blank.
if (m_submode == ChangeSubMode) { if (m_submode == ChangeSubMode) {
@@ -1368,7 +1393,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified,
setAnchor(); setAnchor();
m_submode = DeleteSubMode; m_submode = DeleteSubMode;
moveRight(qMin(count(), rightDist())); moveRight(qMin(count(), rightDist()));
m_dotCommand = QString("%1x").arg(count()); setDotCommand("%1x", count());
finishMovement(); finishMovement();
} else if (key == 'X') { } else if (key == 'X') {
if (leftDist() > 0) { if (leftDist() > 0) {
@@ -1998,16 +2023,16 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle0)
void FakeVimHandler::Private::moveToFirstNonBlankOnLine() void FakeVimHandler::Private::moveToFirstNonBlankOnLine()
{ {
QTextBlock block = m_tc.block();
QTextDocument *doc = m_tc.document(); QTextDocument *doc = m_tc.document();
m_tc.movePosition(StartOfLine, KeepAnchor); const QTextBlock &block = m_tc.block();
int firstPos = m_tc.position(); int firstPos = block.position();
for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) { for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) {
if (!doc->characterAt(i).isSpace()) { if (!doc->characterAt(i).isSpace()) {
m_tc.setPosition(i, KeepAnchor); setPosition(i);
return; return;
} }
} }
setPosition(block.position());
} }
void FakeVimHandler::Private::indentRegion(QChar typedChar) void FakeVimHandler::Private::indentRegion(QChar typedChar)
@@ -2019,7 +2044,7 @@ void FakeVimHandler::Private::indentRegion(QChar typedChar)
qSwap(beginLine, endLine); qSwap(beginLine, endLine);
int amount = 0; int amount = 0;
emit q->indentRegion(&amount, beginLine, endLine, typedChar); emit q->indentRegion(&amount, beginLine, endLine, typedChar);
m_dotCommand = QString("%1==").arg(endLine - beginLine + 1); setDotCommand("%1==", endLine - beginLine + 1);
} }
void FakeVimHandler::Private::shiftRegionRight(int repeat) void FakeVimHandler::Private::shiftRegionRight(int repeat)
@@ -2041,7 +2066,7 @@ void FakeVimHandler::Private::shiftRegionRight(int repeat)
setPosition(firstPos); setPosition(firstPos);
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
m_dotCommand = QString("%1>>").arg(endLine - beginLine + 1); setDotCommand("%1>>", endLine - beginLine + 1);
} }
void FakeVimHandler::Private::shiftRegionLeft(int repeat) void FakeVimHandler::Private::shiftRegionLeft(int repeat)
@@ -2078,17 +2103,20 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat)
setPosition(firstPos); setPosition(firstPos);
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
m_dotCommand = QString("%1<<").arg(endLine - beginLine + 1); setDotCommand("%1<<", endLine - beginLine + 1);
} }
void FakeVimHandler::Private::moveToTargetColumn() void FakeVimHandler::Private::moveToTargetColumn()
{ {
if (m_targetColumn == -1 || m_tc.block().length() <= m_targetColumn) {
const QTextBlock &block = m_tc.block(); const QTextBlock &block = m_tc.block();
int col = m_tc.position() - m_tc.block().position();
if (col == m_targetColumn)
return;
//qDebug() << "CORRECTING COLUMN FROM: " << col << "TO" << m_targetColumn;
if (m_targetColumn == -1 || m_tc.block().length() <= m_targetColumn)
m_tc.setPosition(block.position() + block.length() - 1, KeepAnchor); m_tc.setPosition(block.position() + block.length() - 1, KeepAnchor);
} else { else
m_tc.setPosition(m_tc.block().position() + m_targetColumn, KeepAnchor); m_tc.setPosition(m_tc.block().position() + m_targetColumn, KeepAnchor);
}
} }
/* if simple is given: /* if simple is given:
@@ -2116,7 +2144,7 @@ void FakeVimHandler::Private::moveToWordBoundary(bool simple, bool forward)
int lastClass = -1; int lastClass = -1;
while (true) { while (true) {
QChar c = doc->characterAt(m_tc.position() + (forward ? 1 : -1)); QChar c = doc->characterAt(m_tc.position() + (forward ? 1 : -1));
qDebug() << "EXAMINING: " << c << " AT " << position(); //qDebug() << "EXAMINING: " << c << " AT " << position();
int thisClass = charClass(c, simple); int thisClass = charClass(c, simple);
if (thisClass != lastClass && lastClass != 0) if (thisClass != lastClass && lastClass != 0)
--repeat; --repeat;
@@ -2360,6 +2388,7 @@ QString FakeVimHandler::Private::removeSelectedText()
m_tc.setPosition(pos, KeepAnchor); m_tc.setPosition(pos, KeepAnchor);
QString from = m_tc.selection().toPlainText(); QString from = m_tc.selection().toPlainText();
m_tc.removeSelectedText(); m_tc.removeSelectedText();
setAnchor();
return from; return from;
} }

View File

@@ -602,6 +602,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
addAutoReleasedObject(new ProjectTreeWidgetFactory); addAutoReleasedObject(new ProjectTreeWidgetFactory);
addAutoReleasedObject(new FolderNavigationWidgetFactory); addAutoReleasedObject(new FolderNavigationWidgetFactory);
// > -- Creator 1.0 compatibility code
QStringList oldRecentProjects; QStringList oldRecentProjects;
if (QSettings *s = core->settings()) if (QSettings *s = core->settings())
oldRecentProjects = s->value("ProjectExplorer/RecentProjects/Files", QStringList()).toStringList(); oldRecentProjects = s->value("ProjectExplorer/RecentProjects/Files", QStringList()).toStringList();
@@ -616,6 +617,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
foreach(const QString &s, oldRecentProjects) { foreach(const QString &s, oldRecentProjects) {
m_recentProjects.append(qMakePair(s, QFileInfo(s).fileName())); m_recentProjects.append(qMakePair(s, QFileInfo(s).fileName()));
} }
// < -- Creator 1.0 compatibility code
// TODO restore recentProjects // TODO restore recentProjects
if (QSettings *s = core->settings()) { if (QSettings *s = core->settings()) {
@@ -623,6 +625,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
const QStringList displayNames = s->value("ProjectExplorer/RecentProjects/DisplayNames").toStringList(); const QStringList displayNames = s->value("ProjectExplorer/RecentProjects/DisplayNames").toStringList();
if (fileNames.size() == displayNames.size()) { if (fileNames.size() == displayNames.size()) {
for (int i = 0; i < fileNames.size(); ++i) { for (int i = 0; i < fileNames.size(); ++i) {
if (QFileInfo(fileNames.at(i)).isFile())
m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i))); m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i)));
} }
} }

View File

@@ -1424,16 +1424,12 @@ QString QtVersion::buildDebuggingHelperLibrary()
if (!success) if (!success)
continue; continue;
output += QString("Building debugging helper library in %1\n").arg(directory); // Setup process
output += "\n"; QProcess proc;
output += QString("Runinng %1 ...\n").arg(qmakeCommand());
QProcess qmake;
ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
addToEnvironment(env); addToEnvironment(env);
// TODO this is a hack to get, to be removed and rewritten for 1.2 // TODO this is a hack to get, to be removed and rewritten for 1.2
//
// For MSVC and MINGW, we need a toolchain to get the right environment // For MSVC and MINGW, we need a toolchain to get the right environment
ProjectExplorer::ToolChain *toolChain = 0; ProjectExplorer::ToolChain *toolChain = 0;
ProjectExplorer::ToolChain::ToolChainType t = toolchainType(); ProjectExplorer::ToolChain::ToolChainType t = toolchainType();
@@ -1447,23 +1443,20 @@ QString QtVersion::buildDebuggingHelperLibrary()
toolChain = 0; toolChain = 0;
} }
qmake.setEnvironment(env.toStringList()); proc.setEnvironment(env.toStringList());
qmake.setWorkingDirectory(directory); proc.setWorkingDirectory(directory);
qmake.setProcessChannelMode(QProcess::MergedChannels); proc.setProcessChannelMode(QProcess::MergedChannels);
qmake.start(qmakeCommand(), QStringList()<<"-spec"<< mkspec() <<"gdbmacros.pro"); output += QString("Building debugging helper library in %1\n").arg(directory);
qmake.waitForFinished(); output += "\n";
output += qmake.readAll();
QString make;
// TODO this is butt ugly // TODO this is butt ugly
// only qt4projects have a toolchain() method. (Reason mostly, that in order to create // only qt4projects have a toolchain() method. (Reason mostly, that in order to create
// the toolchain, we need to have the path to gcc // the toolchain, we need to have the path to gcc
// which might depend on environment settings of the project // which might depend on environment settings of the project
// so we hardcode the toolchainType to make conversation here // so we hardcode the toolchainType to make conversation here
// and think about how to fix that later // and think about how to fix that later
QString make;
if (t == ProjectExplorer::ToolChain::MinGW) if (t == ProjectExplorer::ToolChain::MinGW)
make = "mingw32-make.exe"; make = "mingw32-make.exe";
else if(t == ProjectExplorer::ToolChain::MSVC || t == ProjectExplorer::ToolChain::WINCE) else if(t == ProjectExplorer::ToolChain::MSVC || t == ProjectExplorer::ToolChain::WINCE)
@@ -1472,12 +1465,29 @@ QString QtVersion::buildDebuggingHelperLibrary()
make = "make"; make = "make";
QString makeFullPath = env.searchInPath(make); QString makeFullPath = env.searchInPath(make);
if (!makeFullPath.isEmpty()) {
output += QString("Running %1 clean...\n").arg(makeFullPath);
proc.start(makeFullPath, QStringList() << "clean");
proc.waitForFinished();
output += proc.readAll();
} else {
output += QString("%1 not found in PATH\n").arg(make);
break;
}
output += QString("\nRuninng %1 ...\n").arg(qmakeCommand());
proc.start(qmakeCommand(), QStringList()<<"-spec"<< mkspec() <<"gdbmacros.pro");
proc.waitForFinished();
output += proc.readAll();
output += "\n"; output += "\n";
if (!makeFullPath.isEmpty()) { if (!makeFullPath.isEmpty()) {
output += QString("Running %1 ...\n").arg(makeFullPath); output += QString("Running %1 ...\n").arg(makeFullPath);
qmake.start(makeFullPath, QStringList()); proc.start(makeFullPath, QStringList());
qmake.waitForFinished(); proc.waitForFinished();
output += qmake.readAll(); output += proc.readAll();
} else { } else {
output += QString("%1 not found in PATH\n").arg(make); output += QString("%1 not found in PATH\n").arg(make);
} }

View File

@@ -346,14 +346,15 @@ bool ProFileEvaluator::Private::parseLine(const QString &line0)
m_contNextLine = escaped; m_contNextLine = escaped;
if (escaped) { if (escaped) {
m_proitem.chop(1); m_proitem.chop(1);
updateItem();
return true; return true;
} else { } else {
if (!m_syntaxError) { if (!m_syntaxError) {
updateItem(); updateItem();
if (!m_contNextLine)
finalizeBlock(); finalizeBlock();
return true;
} }
return !m_syntaxError; return false;
} }
} }

View File

@@ -235,26 +235,26 @@ examples/xml/xmlstreamlint/xmlstreamlint
examples/xmlpatterns/filetree/filetree examples/xmlpatterns/filetree/filetree
examples/xmlpatterns/qobjectxmlmodel/qobjectxmlmodel examples/xmlpatterns/qobjectxmlmodel/qobjectxmlmodel
examples/xmlpatterns/recipes/recipes examples/xmlpatterns/recipes/recipes
lib/libQt3Support.so.4.5.0 lib/libQt3Support.so.4.5.1
lib/libQtAssistantClient.so.4.5.0 lib/libQtAssistantClient.so.4.5.1
lib/libQtCLucene.so.4.5.0 lib/libQtCLucene.so.4.5.1
lib/libQtCore.so.4.5.0 lib/libQtCore.so.4.5.1
lib/libQtDBus.so.4.5.0 lib/libQtDBus.so.4.5.1
lib/libQtDesigner.so.4.5.0 lib/libQtDesigner.so.4.5.1
lib/libQtDesignerComponents.so.4.5.0 lib/libQtDesignerComponents.so.4.5.1
lib/libQtGui.so.4.5.0 lib/libQtGui.so.4.5.1
lib/libQtHelp.so.4.5.0 lib/libQtHelp.so.4.5.1
lib/libQtNetwork.so.4.5.0 lib/libQtNetwork.so.4.5.1
lib/libQtOpenGL.so.4.5.0 lib/libQtOpenGL.so.4.5.1
lib/libQtScript.so.4.5.0 lib/libQtScript.so.4.5.1
lib/libQtScriptTools.so.4.5.0 lib/libQtScriptTools.so.4.5.1
lib/libQtSql.so.4.5.0 lib/libQtSql.so.4.5.1
lib/libQtSvg.so.4.5.0 lib/libQtSvg.so.4.5.1
lib/libQtTest.so.4.5.0 lib/libQtTest.so.4.5.1
lib/libQtUiTools.a lib/libQtUiTools.a
lib/libQtWebKit.so.4.5.0 lib/libQtWebKit.so.4.5.1
lib/libQtXml.so.4.5.0 lib/libQtXml.so.4.5.1
lib/libQtXmlPatterns.so.4.5.0 lib/libQtXmlPatterns.so.4.5.1
plugins/accessible/libqtaccessiblecompatwidgets.so plugins/accessible/libqtaccessiblecompatwidgets.so
plugins/accessible/libqtaccessiblewidgets.so plugins/accessible/libqtaccessiblewidgets.so
plugins/codecs/libqcncodecs.so plugins/codecs/libqcncodecs.so

View File

@@ -79,6 +79,9 @@ private slots:
void mi10() { testMi(test10); } void mi10() { testMi(test10); }
void mi11() { testMi(test11); } void mi11() { testMi(test11); }
void mi12() { testMi(test12); } void mi12() { testMi(test12); }
void infoBreak();
void runQtc(); void runQtc();
public slots: public slots:
@@ -100,6 +103,41 @@ static QByteArray stripped(QByteArray ba)
return ba; return ba;
} }
void tst_Debugger::infoBreak()
{
// This tests the regular expression used in GdbEngine::extractDataFromInfoBreak
// to discover breakpoints in constructors.
// Copied from gdbengine.cpp:
QRegExp re("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)");
re.setMinimal(true);
QCOMPARE(re.indexIn(
"2 breakpoint keep y <MULTIPLE> 0x0040168e\n"
"2.1 y 0x0040168e "
"in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7\n"
"2.2 y 0x00401792 "
"in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7\n"), 33);
QCOMPARE(re.cap(1), QString("0x0040168e"));
QCOMPARE(re.cap(2).trimmed(), QString("MainWindow::MainWindow(QWidget*)"));
QCOMPARE(re.cap(3), QString("mainwindow.cpp"));
QCOMPARE(re.cap(4), QString("7"));
QCOMPARE(re.indexIn(
"Num Type Disp Enb Address What"
"4 breakpoint keep y <MULTIPLE> 0x00000000004066ad"
"4.1 y 0x00000000004066ad in CTorTester"
" at /main/tests/manual/gdbdebugger/simple/app.cpp:124"), 88);
QCOMPARE(re.cap(1), QString("0x00000000004066ad"));
QCOMPARE(re.cap(2).trimmed(), QString("CTorTester"));
QCOMPARE(re.cap(3), QString("/main/tests/manual/gdbdebugger/simple/app.cpp"));
QCOMPARE(re.cap(4), QString("124"));
}
void tst_Debugger::readStandardOutput() void tst_Debugger::readStandardOutput()
{ {
qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput()); qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput());

View File

@@ -55,13 +55,17 @@ public slots:
void changeExtraInformation(const QString &info) { m_infoMessage = info; } void changeExtraInformation(const QString &info) { m_infoMessage = info; }
private slots: private slots:
void commandDollar(); // command mode
void commandDown(); void command_cc();
void commandLeft(); void command_dd();
void commandRight(); void command_dollar();
void commandI(); void command_down();
void commandUp(); void command_e();
void commandW(); void command_i();
void command_left();
void command_right();
void command_up();
void command_w();
private: private:
void setup(); void setup();
@@ -73,6 +77,9 @@ private:
const char* file, int line); const char* file, int line);
QString insertCursor(const QString &needle0); QString insertCursor(const QString &needle0);
QString lmid(int i, int n = -1) const
{ return QStringList(l.mid(i, n)).join("\n"); }
QTextEdit *m_textedit; QTextEdit *m_textedit;
QPlainTextEdit *m_plaintextedit; QPlainTextEdit *m_plaintextedit;
FakeVimHandler *m_handler; FakeVimHandler *m_handler;
@@ -82,6 +89,8 @@ private:
QString m_statusData; QString m_statusData;
QString m_infoMessage; QString m_infoMessage;
// the individual lines
static const QStringList l; // identifier intentionally kept short
static const QString lines; static const QString lines;
static const QString escape; static const QString escape;
}; };
@@ -100,8 +109,11 @@ const QString tst_FakeVim::lines =
" return app.exec();\n" " return app.exec();\n"
"}\n"; "}\n";
const QStringList tst_FakeVim::l = tst_FakeVim::lines.split('\n');
const QString tst_FakeVim::escape = QChar(27); const QString tst_FakeVim::escape = QChar(27);
tst_FakeVim::tst_FakeVim(bool usePlainTextEdit) tst_FakeVim::tst_FakeVim(bool usePlainTextEdit)
{ {
if (usePlainTextEdit) { if (usePlainTextEdit) {
@@ -170,16 +182,16 @@ bool tst_FakeVim::checkContentsHelper(QString want, const char* file, int line)
QStringList wantlist = want.split('\n'); QStringList wantlist = want.split('\n');
QStringList gotlist = got.split('\n'); QStringList gotlist = got.split('\n');
if (!QTest::qCompare(gotlist.size(), wantlist.size(), "", "", file, line)) { if (!QTest::qCompare(gotlist.size(), wantlist.size(), "", "", file, line)) {
qDebug() << "WANT: " << want; qDebug() << "0 WANT: " << want;
qDebug() << "GOT: " << got; qDebug() << "0 GOT: " << got;
return false; return false;
} }
for (int i = 0; i < wantlist.size() && i < gotlist.size(); ++i) { for (int i = 0; i < wantlist.size() && i < gotlist.size(); ++i) {
QString g = QString("line %1: %2").arg(i + 1).arg(gotlist.at(i)); QString g = QString("line %1: %2").arg(i + 1).arg(gotlist.at(i));
QString w = QString("line %1: %2").arg(i + 1).arg(wantlist.at(i)); QString w = QString("line %1: %2").arg(i + 1).arg(wantlist.at(i));
if (!QTest::qCompare(g, w, "", "", file, line)) { if (!QTest::qCompare(g, w, "", "", file, line)) {
qDebug() << "WANT: " << want; qDebug() << "1 WANT: " << want;
qDebug() << "GOT: " << got; qDebug() << "1 GOT: " << got;
return false; return false;
} }
} }
@@ -222,11 +234,78 @@ QString tst_FakeVim::insertCursor(const QString &needle0)
needle.remove('@'); needle.remove('@');
QString lines0 = lines; QString lines0 = lines;
int pos = lines0.indexOf(needle); int pos = lines0.indexOf(needle);
if (pos == -1)
qDebug() << "Cannot find: \n----\n" + needle + "\n----\n";
lines0.replace(pos, needle.size(), needle0); lines0.replace(pos, needle.size(), needle0);
return lines0; return lines0;
} }
void tst_FakeVim::commandI()
//////////////////////////////////////////////////////////////////////////
//
// Command mode
//
//////////////////////////////////////////////////////////////////////////
void tst_FakeVim::command_cc()
{
setup();
move("j", "@" + l[1]);
check("ccabc" + escape, l[0] + "\nab@c\n" + lmid(2));
check("ccabc" + escape, l[0] + "\nab@c\n" + lmid(2));
check(".", l[0] + "\nab@c\n" + lmid(2));
check("j", l[0] + "\nabc\n#i@nclude <QtGui>\n" + lmid(3));
check("3ccxyz" + escape, l[0] + "\nabc\nxy@z\n" + lmid(5));
}
void tst_FakeVim::command_dd()
{
setup();
move("j", "@" + l[1]);
check("dd", l[0] + "\n@" + lmid(2));
check(".", l[0] + "\n@" + lmid(3));
check("3dd", l[0] + "\n@" + lmid(6));
}
void tst_FakeVim::command_dollar()
{
setup();
move("j$", "<QtCore>@");
move("j$", "<QtGui>@");
move("2j", ")@");
}
void tst_FakeVim::command_down()
{
setup();
move("j", "@" + l[1]);
move("3j", "@int main");
move("4j", "@ return app.exec()");
}
void tst_FakeVim::command_e()
{
setup();
move("e", "@#include <QtCore");
move("e", "#includ@e <QtCore");
move("e", "#include @<QtCore");
move("3e", "@#include <QtGui");
move("e", "#includ@e <QtGui");
move("e", "#include @<QtGui");
move("e", "#include <QtGu@i");
move("4e", "int main@(int argc, char *argv[])");
move("e", "int main(in@t argc, char *argv[])");
move("e", "int main(int arg@c, char *argv[])");
move("e", "int main(int argc@, char *argv[])");
move("e", "int main(int argc, cha@r *argv[])");
move("e", "int main(int argc, char @*argv[])");
move("e", "int main(int argc, char *arg@v[])");
move("e", "int main(int argc, char *argv[]@)");
move("e", "@{");
move("10k","@\n"); // home.
}
void tst_FakeVim::command_i()
{ {
setup(); setup();
@@ -255,40 +334,7 @@ return;
check("u", "@" + lines); check("u", "@" + lines);
} }
void tst_FakeVim::commandDollar() void tst_FakeVim::command_left()
{
setup();
move("j$", "<QtCore>@");
move("j$", "<QtGui>@");
move("2j", ")@");
}
void tst_FakeVim::commandDown()
{
setup();
move("j", "@#include <QtCore");
move("3j", "@int main");
move("4j", "@ return app.exec()");
}
void tst_FakeVim::commandUp()
{
setup();
move("j", "@#include <QtCore");
move("3j", "@int main");
move("4j", "@ return app.exec()");
}
void tst_FakeVim::commandRight()
{
setup();
move("4j", "@int main");
move("l", "i@nt main");
move("3l", "int @main");
move("50l", "argv[])@");
}
void tst_FakeVim::commandLeft()
{ {
setup(); setup();
move("4j", "@int main"); move("4j", "@int main");
@@ -299,16 +345,44 @@ void tst_FakeVim::commandLeft()
move("50h", "@int main"); move("50h", "@int main");
} }
void tst_FakeVim::commandW() void tst_FakeVim::command_right()
{
setup();
move("4j", "@int main");
move("l", "i@nt main");
move("3l", "int @main");
move("50l", "argv[])@");
}
void tst_FakeVim::command_up()
{
setup();
move("j", "@#include <QtCore");
move("3j", "@int main");
move("4j", "@ return app.exec()");
}
void tst_FakeVim::command_w()
{ {
setup(); setup();
move("w", "@#include <QtCore"); move("w", "@#include <QtCore");
move("w", "#@include <QtCore"); move("w", "#@include <QtCore");
move("w", "#include @<QtCore"); move("w", "#include @<QtCore");
move("3w", "@#include <QtGui"); move("3w", "@#include <QtGui");
move("w", "#@include <QtGui");
move("w", "#include @<QtGui");
move("w", "#include <@QtGui");
move("4w", "int main@(int argc, char *argv[])");
move("w", "int main(@int argc, char *argv[])");
move("w", "int main(int @argc, char *argv[])");
move("w", "int main(int argc@, char *argv[])");
move("w", "int main(int argc, @char *argv[])");
move("w", "int main(int argc, char @*argv[])");
move("w", "int main(int argc, char *@argv[])");
move("w", "int main(int argc, char *argv@[])");
move("w", "@{");
} }
/* /*
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@@ -321,6 +395,14 @@ int main(int argc, char *argv[])
} }
*/ */
//////////////////////////////////////////////////////////////////////////
//
// Main
//
//////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[]) \ int main(int argc, char *argv[]) \
{ {
int res = 0; int res = 0;

View File

@@ -87,6 +87,12 @@ public:
b = 2 + s + t; b = 2 + s + t;
a += 1; a += 1;
} }
~Foo()
{
a = 5;
}
void doit() void doit()
{ {
static QObject ob; static QObject ob;