diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index a59897820a3..b6df29ba577 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -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. diff --git a/share/qtcreator/gdbmacros/gdbmacros.pro b/share/qtcreator/gdbmacros/gdbmacros.pro index bd1c07b9686..00c7b2403c8 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.pro +++ b/share/qtcreator/gdbmacros/gdbmacros.pro @@ -1,3 +1,7 @@ TEMPLATE = lib CONFIG += shared +linux-* { +CONFIG -= release +CONFIG += debug +} SOURCES=gdbmacros.cpp diff --git a/src/app/app.pro b/src/app/app.pro index 69f677dacb7..0894b2a7261 100644 --- a/src/app/app.pro +++ b/src/app/app.pro @@ -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 } diff --git a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp index fcfef28f997..51d57b9e09b 100644 --- a/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeopenprojectwizard.cpp @@ -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); } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index d1fe107412d..ffd333d23fa 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -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; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index 4629aa3d5fc..0ed79cfc489 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -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 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 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) { diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index f8c734c0114..49c5f4576ba 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -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 findQtDir(const ProjectExplorer::Environment &env); int m_projectContext; int m_projectLanguage; CMakeSettingsPage *m_settingsPage; diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index f9b2cde57b2..ee0c58e0a4c 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -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; diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index fa4b05740e7..81a1025a4ee 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -208,6 +208,8 @@ private slots: void goBackInNavigationHistory(); void goForwardInNavigationHistory(); void makeCurrentEditorWritable(); + +public slots: void split(Qt::Orientation orientation); void split(); void splitSideBySide(); diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 7a6ff93fbc6..0ecf1fa463d 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -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); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index c4cbbc4cf71..3b2d20b0cd5 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -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 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.") diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index b5f5868dcf5..4cb7dcef659 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -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; diff --git a/src/plugins/debugger/gdboptionpage.ui b/src/plugins/debugger/gdboptionpage.ui new file mode 100644 index 00000000000..7c7c20b957c --- /dev/null +++ b/src/plugins/debugger/gdboptionpage.ui @@ -0,0 +1,232 @@ + + + GdbOptionPage + + + + 0 + 0 + 429 + 452 + + + + Form + + + + + + Gdb interaction + + + + 9 + + + 6 + + + + + + + + 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. + + + Gdb location: + + + + + + + Environment: + + + environmentEdit + + + + + + + This is either empty or points to a file containing gdb commands that will be executed immediately after gdb starts up. + + + Gdb startup script: + + + + + + + + + + + + + + + + Behaviour of breakpoint setting in plugins + + + + + + This is the slowest but safest option. + + + Try to set breakpoints in plugins always automatically. + + + + + + + Try to set breakpoints in selected plugins + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 10 + 10 + + + + + + + + Matching regular expression: + + + + + + + + + + + + Never set breakpoints in plugins automatically + + + + + + + + + + User interface + + + + + + Checking this will populate the source file view automatically but might slow down debugger startup considerably. + + + Populate source file view automatically + + + + + + + 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. + + + Skip known frames when stepping + + + + + + + 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. + + + Use tooltips while debugging + + + + + + + + + Maximal stack depth: + + + + + + + Qt::LeftToRight + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + <unlimited> + + + 999 + + + 5 + + + 10 + + + + + + + + + + + + Qt::Vertical + + + + 10 + 1 + + + + + + + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
+ + +
diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 42e42f5f0b6..eea64c4bca0 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -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; diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index f6e2fd01cb8..71ac3bb1e6c 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -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()); QModelIndex mi0 = idx.sibling(idx.row(), 0); QString exp = model()->data(mi0).toString(); - QModelIndex mi1 = idx.sibling(idx.row(), 0); - QString value = model()->data(mi1).toString(); menu.addSeparator(); int type = (m_type == LocalsType) ? WatchExpression : RemoveWatchExpression; diff --git a/src/plugins/fakevim/README b/src/plugins/fakevim/README new file mode 100644 index 00000000000..f901e5984a0 --- /dev/null +++ b/src/plugins/fakevim/README @@ -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 + diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index cc6e580a8f5..407b4e33801 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -29,28 +29,33 @@ #include "fakevimhandler.h" -// Please do not add any direct dependencies to other Qt Creator code here. -// 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 -// allows easy reuse with any QTextEdit or QPlainTextEdit derived class. - - -// Some conventions: // -// 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' -// concepts. +// ATTENTION: // -// Do not pass QTextCursor etc around unless really needed. Convert -// early to line/column. +// 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 +// 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. // -// There is always a "current" cursor (m_tc). A current "region of interest" -// spans between m_anchor (== anchor()) and m_tc.position() (== position()) -// The value of m_tc.anchor() is not used. +// 2 There are a few auto tests located in ../../../tests/auto/fakevim. +// 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 +// the 1 based line are not nice it matches vim's and QTextEdit's 'line' +// concepts. +// +// Do not pass QTextCursor etc around unless really needed. Convert +// early to line/column. +// +// There is always a "current" cursor (m_tc). A current "region of interest" +// spans between m_anchor (== anchor()) and m_tc.position() (== position()) +// The value of m_tc.anchor() is not used. +// #include - #include #include #include @@ -277,7 +282,7 @@ public: // to reduce line noise void moveToEndOfDocument() { m_tc.movePosition(EndOfDocument, MoveAnchor); } - void moveToStartOfLine() { m_tc.movePosition(StartOfLine, MoveAnchor); } + void moveToStartOfLine(); void moveToEndOfLine(); void moveUp(int n = 1) { moveDown(-n); } void moveDown(int n = 1); // { m_tc.movePosition(Down, MoveAnchor, n); } @@ -352,6 +357,8 @@ public: // extra data for '.' 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; 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); #else const int col = m_tc.position() - m_tc.block().position(); - const int line = m_tc.block().blockNumber(); - const QTextBlock &block = m_tc.document()->findBlockByNumber(line + n); + const int lastLine = m_tc.document()->lastBlock().blockNumber(); + 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(); setPosition(pos + qMin(block.length() - 1, col)); moveToTargetColumn(); @@ -631,6 +639,17 @@ void FakeVimHandler::Private::moveToEndOfLine() #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) { //qDebug() << "ANCHOR: " << position() << anchor(); @@ -655,7 +674,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) if (anchor() >= position()) m_anchor++; if (!dotCommand.isEmpty()) - m_dotCommand = "c" + dotCommand; + setDotCommand("c" + dotCommand); QString text = removeSelectedText(); //qDebug() << "CHANGING TO INSERT MODE" << text; m_registers[m_register] = text; @@ -667,7 +686,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) if (anchor() >= position()) m_anchor++; if (!dotCommand.isEmpty()) - m_dotCommand = "d" + dotCommand; + setDotCommand("d" + dotCommand); m_registers[m_register] = removeSelectedText(); m_submode = NoSubMode; if (atEndOfLine()) @@ -693,8 +712,6 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) updateMiniBuffer(); } - moveToTargetColumn(); - m_moveType = MoveInclusive; m_mvcount.clear(); m_opcount.clear(); @@ -846,13 +863,19 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, } else if (m_submode == RegisterSubMode) { m_register = key; m_submode = NoSubMode; - } else if (m_submode == ChangeSubMode && key == 'c') { - moveToStartOfLine(); + } else if (m_submode == ChangeSubMode && key == 'c') { // tested + moveDown(count() - 1); + moveToEndOfLine(); + moveLeft(); setAnchor(); - moveDown(count()); + moveToStartOfLine(); + setTargetColumn(); + moveUp(count() - 1); m_moveType = MoveLineWise; - finishMovement("c"); - } else if (m_submode == DeleteSubMode && key == 'd') { + m_lastInsertion.clear(); + setDotCommand("%1cc", count()); + finishMovement(); + } else if (m_submode == DeleteSubMode && key == 'd') { // tested moveToStartOfLine(); setAnchor(); moveDown(count()); @@ -868,19 +891,19 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, setAnchor(); moveDown(count() - 1); m_moveType = MoveLineWise; - m_dotCommand = QString("%1<<").arg(count()); + setDotCommand("%1<<", count()); finishMovement(); } else if (m_submode == ShiftRightSubMode && key == '>') { setAnchor(); moveDown(count() - 1); m_moveType = MoveLineWise; - m_dotCommand = QString("%1>>").arg(count()); + setDotCommand("%1>>", count()); finishMovement(); } else if (m_submode == IndentSubMode && key == '=') { setAnchor(); moveDown(count() - 1); m_moveType = MoveLineWise; - m_dotCommand = QString("%1>>").arg(count()); + setDotCommand("%1>>", count()); finishMovement(); } else if (m_submode == ZSubMode) { //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_moveType = MoveExclusive; m_submode = NoSubMode; - m_dotCommand = QString("%1r%2").arg(count()).arg(text); + setDotCommand("%1r" + text, count()); finishMovement(); } else { m_submode = NoSubMode; @@ -1072,6 +1095,8 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, m_mode = InsertMode; moveToEndOfLine(); m_lastInsertion.clear(); + } else if (key == control('a')) { + // FIXME: eat it to prevent the global "select all" shortcut to trigger } else if (key == 'b') { m_moveType = MoveExclusive; moveToWordBoundary(false, false); @@ -1124,7 +1149,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, handleStartOfLine(); scrollToLineInDocument(cursorLineInDocument() - sline); finishMovement(); - } else if (key == 'e') { + } else if (key == 'e') { // tested m_moveType = MoveInclusive; moveToWordBoundary(false, true); finishMovement(); @@ -1174,13 +1199,13 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, handleStartOfLine(); finishMovement(); } else if (key == 'i') { - m_dotCommand = "i"; //QString("%1i").arg(count()); + setDotCommand("i"); // setDotCommand("%1i", count()); enterInsertMode(); updateMiniBuffer(); if (atEndOfLine()) moveLeft(); } else if (key == 'I') { - m_dotCommand = "I"; //QString("%1I").arg(count()); + setDotCommand("I"); // setDotCommand("%1I", count()); enterInsertMode(); if (m_gflag) moveToStartOfLine(); @@ -1255,7 +1280,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, search(lastSearchString(), !m_lastSearchForward); recordJump(); } else if (key == 'o' || key == 'O') { - m_dotCommand = QString("%1o").arg(count()); + setDotCommand("%1o", count()); enterInsertMode(); moveToFirstNonBlankOnLine(); if (key == 'O') @@ -1292,18 +1317,18 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, moveLeft(); } } - m_dotCommand = QString("%1p").arg(count()); + setDotCommand("%1p", count()); finishMovement(); } else if (key == 'r') { m_submode = ReplaceSubMode; - m_dotCommand = "r"; + setDotCommand("r"); } else if (key == 'R') { // FIXME: right now we repeat the insertion count() times, // but not the deletion m_lastInsertion.clear(); m_mode = InsertMode; m_submode = ReplaceSubMode; - m_dotCommand = "R"; + setDotCommand("R"); } else if (key == control('r')) { redo(); } else if (key == 's') { @@ -1312,7 +1337,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, setAnchor(); moveRight(qMin(count(), rightDist())); m_registers[m_register] = removeSelectedText(); - m_dotCommand = "s"; //QString("%1s").arg(count()); + setDotCommand("s"); // setDotCommand("%1s", count()); m_opcount.clear(); m_mvcount.clear(); enterInsertMode(); @@ -1339,7 +1364,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, enterVisualMode(VisualLineMode); } else if (key == control('v')) { 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 // cursor is on a non-blank. if (m_submode == ChangeSubMode) { @@ -1368,7 +1393,7 @@ EventResult FakeVimHandler::Private::handleCommandMode(int key, int unmodified, setAnchor(); m_submode = DeleteSubMode; moveRight(qMin(count(), rightDist())); - m_dotCommand = QString("%1x").arg(count()); + setDotCommand("%1x", count()); finishMovement(); } else if (key == 'X') { if (leftDist() > 0) { @@ -1998,16 +2023,16 @@ void FakeVimHandler::Private::highlightMatches(const QString &needle0) void FakeVimHandler::Private::moveToFirstNonBlankOnLine() { - QTextBlock block = m_tc.block(); QTextDocument *doc = m_tc.document(); - m_tc.movePosition(StartOfLine, KeepAnchor); - int firstPos = m_tc.position(); + const QTextBlock &block = m_tc.block(); + int firstPos = block.position(); for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) { if (!doc->characterAt(i).isSpace()) { - m_tc.setPosition(i, KeepAnchor); + setPosition(i); return; } } + setPosition(block.position()); } void FakeVimHandler::Private::indentRegion(QChar typedChar) @@ -2019,7 +2044,7 @@ void FakeVimHandler::Private::indentRegion(QChar typedChar) qSwap(beginLine, endLine); int amount = 0; 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) @@ -2041,7 +2066,7 @@ void FakeVimHandler::Private::shiftRegionRight(int repeat) setPosition(firstPos); moveToFirstNonBlankOnLine(); - m_dotCommand = QString("%1>>").arg(endLine - beginLine + 1); + setDotCommand("%1>>", endLine - beginLine + 1); } void FakeVimHandler::Private::shiftRegionLeft(int repeat) @@ -2078,17 +2103,20 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat) setPosition(firstPos); moveToFirstNonBlankOnLine(); - m_dotCommand = QString("%1<<").arg(endLine - beginLine + 1); + setDotCommand("%1<<", endLine - beginLine + 1); } 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); - } else { + else m_tc.setPosition(m_tc.block().position() + m_targetColumn, KeepAnchor); - } } /* if simple is given: @@ -2116,7 +2144,7 @@ void FakeVimHandler::Private::moveToWordBoundary(bool simple, bool forward) int lastClass = -1; while (true) { 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); if (thisClass != lastClass && lastClass != 0) --repeat; @@ -2360,6 +2388,7 @@ QString FakeVimHandler::Private::removeSelectedText() m_tc.setPosition(pos, KeepAnchor); QString from = m_tc.selection().toPlainText(); m_tc.removeSelectedText(); + setAnchor(); return from; } diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 56058e782b5..06bf33a3e3f 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -602,6 +602,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new ProjectTreeWidgetFactory); addAutoReleasedObject(new FolderNavigationWidgetFactory); + // > -- Creator 1.0 compatibility code QStringList oldRecentProjects; if (QSettings *s = core->settings()) 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) { m_recentProjects.append(qMakePair(s, QFileInfo(s).fileName())); } + // < -- Creator 1.0 compatibility code // TODO restore recentProjects if (QSettings *s = core->settings()) { @@ -623,7 +625,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er const QStringList displayNames = s->value("ProjectExplorer/RecentProjects/DisplayNames").toStringList(); if (fileNames.size() == displayNames.size()) { for (int i = 0; i < fileNames.size(); ++i) { - m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i))); + if (QFileInfo(fileNames.at(i)).isFile()) + m_recentProjects.append(qMakePair(fileNames.at(i), displayNames.at(i))); } } } diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 6086c5ba4b3..89e233b293b 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1424,17 +1424,13 @@ QString QtVersion::buildDebuggingHelperLibrary() if (!success) continue; - output += QString("Building debugging helper library in %1\n").arg(directory); - output += "\n"; - output += QString("Runinng %1 ...\n").arg(qmakeCommand()); + // Setup process + QProcess proc; - QProcess qmake; ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); addToEnvironment(env); - // 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::ToolChainType t = toolchainType(); if (t == ProjectExplorer::ToolChain::MinGW) @@ -1447,23 +1443,20 @@ QString QtVersion::buildDebuggingHelperLibrary() toolChain = 0; } - qmake.setEnvironment(env.toStringList()); - qmake.setWorkingDirectory(directory); - qmake.setProcessChannelMode(QProcess::MergedChannels); + proc.setEnvironment(env.toStringList()); + proc.setWorkingDirectory(directory); + proc.setProcessChannelMode(QProcess::MergedChannels); - qmake.start(qmakeCommand(), QStringList()<<"-spec"<< mkspec() <<"gdbmacros.pro"); - qmake.waitForFinished(); - - output += qmake.readAll(); + output += QString("Building debugging helper library in %1\n").arg(directory); + output += "\n"; + QString make; // TODO this is butt ugly // only qt4projects have a toolchain() method. (Reason mostly, that in order to create // the toolchain, we need to have the path to gcc // which might depend on environment settings of the project // so we hardcode the toolchainType to make conversation here // and think about how to fix that later - - QString make; if (t == ProjectExplorer::ToolChain::MinGW) make = "mingw32-make.exe"; else if(t == ProjectExplorer::ToolChain::MSVC || t == ProjectExplorer::ToolChain::WINCE) @@ -1472,12 +1465,29 @@ QString QtVersion::buildDebuggingHelperLibrary() make = "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"; if (!makeFullPath.isEmpty()) { output += QString("Running %1 ...\n").arg(makeFullPath); - qmake.start(makeFullPath, QStringList()); - qmake.waitForFinished(); - output += qmake.readAll(); + proc.start(makeFullPath, QStringList()); + proc.waitForFinished(); + output += proc.readAll(); } else { output += QString("%1 not found in PATH\n").arg(make); } diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 1313f7c0306..95bd578d9fc 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -346,14 +346,15 @@ bool ProFileEvaluator::Private::parseLine(const QString &line0) m_contNextLine = escaped; if (escaped) { m_proitem.chop(1); + updateItem(); return true; } else { if (!m_syntaxError) { updateItem(); - if (!m_contNextLine) - finalizeBlock(); + finalizeBlock(); + return true; } - return !m_syntaxError; + return false; } } diff --git a/src/tools/qpatch/files-to-patch-linux b/src/tools/qpatch/files-to-patch-linux index 8fa0394d0b3..da166075843 100644 --- a/src/tools/qpatch/files-to-patch-linux +++ b/src/tools/qpatch/files-to-patch-linux @@ -235,26 +235,26 @@ examples/xml/xmlstreamlint/xmlstreamlint examples/xmlpatterns/filetree/filetree examples/xmlpatterns/qobjectxmlmodel/qobjectxmlmodel examples/xmlpatterns/recipes/recipes -lib/libQt3Support.so.4.5.0 -lib/libQtAssistantClient.so.4.5.0 -lib/libQtCLucene.so.4.5.0 -lib/libQtCore.so.4.5.0 -lib/libQtDBus.so.4.5.0 -lib/libQtDesigner.so.4.5.0 -lib/libQtDesignerComponents.so.4.5.0 -lib/libQtGui.so.4.5.0 -lib/libQtHelp.so.4.5.0 -lib/libQtNetwork.so.4.5.0 -lib/libQtOpenGL.so.4.5.0 -lib/libQtScript.so.4.5.0 -lib/libQtScriptTools.so.4.5.0 -lib/libQtSql.so.4.5.0 -lib/libQtSvg.so.4.5.0 -lib/libQtTest.so.4.5.0 +lib/libQt3Support.so.4.5.1 +lib/libQtAssistantClient.so.4.5.1 +lib/libQtCLucene.so.4.5.1 +lib/libQtCore.so.4.5.1 +lib/libQtDBus.so.4.5.1 +lib/libQtDesigner.so.4.5.1 +lib/libQtDesignerComponents.so.4.5.1 +lib/libQtGui.so.4.5.1 +lib/libQtHelp.so.4.5.1 +lib/libQtNetwork.so.4.5.1 +lib/libQtOpenGL.so.4.5.1 +lib/libQtScript.so.4.5.1 +lib/libQtScriptTools.so.4.5.1 +lib/libQtSql.so.4.5.1 +lib/libQtSvg.so.4.5.1 +lib/libQtTest.so.4.5.1 lib/libQtUiTools.a -lib/libQtWebKit.so.4.5.0 -lib/libQtXml.so.4.5.0 -lib/libQtXmlPatterns.so.4.5.0 +lib/libQtWebKit.so.4.5.1 +lib/libQtXml.so.4.5.1 +lib/libQtXmlPatterns.so.4.5.1 plugins/accessible/libqtaccessiblecompatwidgets.so plugins/accessible/libqtaccessiblewidgets.so plugins/codecs/libqcncodecs.so diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp index 13ece24e546..4e7eeeeb61f 100644 --- a/tests/auto/debugger/main.cpp +++ b/tests/auto/debugger/main.cpp @@ -79,6 +79,9 @@ private slots: void mi10() { testMi(test10); } void mi11() { testMi(test11); } void mi12() { testMi(test12); } + + void infoBreak(); + void runQtc(); public slots: @@ -100,6 +103,41 @@ static QByteArray stripped(QByteArray 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 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 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() { qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput()); diff --git a/tests/auto/fakevim/main.cpp b/tests/auto/fakevim/main.cpp index a1ac3be7826..fd5b06f0931 100644 --- a/tests/auto/fakevim/main.cpp +++ b/tests/auto/fakevim/main.cpp @@ -55,13 +55,17 @@ public slots: void changeExtraInformation(const QString &info) { m_infoMessage = info; } private slots: - void commandDollar(); - void commandDown(); - void commandLeft(); - void commandRight(); - void commandI(); - void commandUp(); - void commandW(); + // command mode + void command_cc(); + void command_dd(); + void command_dollar(); + void command_down(); + void command_e(); + void command_i(); + void command_left(); + void command_right(); + void command_up(); + void command_w(); private: void setup(); @@ -73,6 +77,9 @@ private: const char* file, int line); QString insertCursor(const QString &needle0); + QString lmid(int i, int n = -1) const + { return QStringList(l.mid(i, n)).join("\n"); } + QTextEdit *m_textedit; QPlainTextEdit *m_plaintextedit; FakeVimHandler *m_handler; @@ -82,6 +89,8 @@ private: QString m_statusData; QString m_infoMessage; + // the individual lines + static const QStringList l; // identifier intentionally kept short static const QString lines; static const QString escape; }; @@ -100,8 +109,11 @@ const QString tst_FakeVim::lines = " return app.exec();\n" "}\n"; +const QStringList tst_FakeVim::l = tst_FakeVim::lines.split('\n'); + const QString tst_FakeVim::escape = QChar(27); + tst_FakeVim::tst_FakeVim(bool usePlainTextEdit) { if (usePlainTextEdit) { @@ -170,16 +182,16 @@ bool tst_FakeVim::checkContentsHelper(QString want, const char* file, int line) QStringList wantlist = want.split('\n'); QStringList gotlist = got.split('\n'); if (!QTest::qCompare(gotlist.size(), wantlist.size(), "", "", file, line)) { - qDebug() << "WANT: " << want; - qDebug() << "GOT: " << got; + qDebug() << "0 WANT: " << want; + qDebug() << "0 GOT: " << got; return false; } 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 w = QString("line %1: %2").arg(i + 1).arg(wantlist.at(i)); if (!QTest::qCompare(g, w, "", "", file, line)) { - qDebug() << "WANT: " << want; - qDebug() << "GOT: " << got; + qDebug() << "1 WANT: " << want; + qDebug() << "1 GOT: " << got; return false; } } @@ -222,11 +234,78 @@ QString tst_FakeVim::insertCursor(const QString &needle0) needle.remove('@'); QString lines0 = lines; int pos = lines0.indexOf(needle); + if (pos == -1) + qDebug() << "Cannot find: \n----\n" + needle + "\n----\n"; lines0.replace(pos, needle.size(), needle0); 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 \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$", "@"); + move("j$", "@"); + 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 @"); - move("j$", "@"); - move("2j", ")@"); -} - -void tst_FakeVim::commandDown() -{ - setup(); - move("j", "@#include @@ -321,6 +395,14 @@ int main(int argc, char *argv[]) } */ + + +////////////////////////////////////////////////////////////////////////// +// +// Main +// +////////////////////////////////////////////////////////////////////////// + int main(int argc, char *argv[]) \ { int res = 0; diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 427cbf452fe..76b35c9ce77 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -87,6 +87,12 @@ public: b = 2 + s + t; a += 1; } + + ~Foo() + { + a = 5; + } + void doit() { static QObject ob;