diff --git a/.gitignore b/.gitignore index 2c79a07b7596f5d67200cd00235864337c217321..e0c76e75e46199e732be9441bf3ad6863279aa4d 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ src/xml/lib/ # -------- bin/*.dll bin/qtcreator.bin +bin/qtcreator_process_stub bin/qtcreator.exe doc/qtcreator.qch tests/manual/cplusplus/cplusplus0 diff --git a/dist/changes-1.1.0 b/dist/changes-1.1.0 index 28e9f0c9b612e0c27ce1f29f4ca580822e9dddac..3fa27a9763cc0d5c6b4e12f5c432891b90c8f80c 100644 --- a/dist/changes-1.1.0 +++ b/dist/changes-1.1.0 @@ -18,9 +18,6 @@ Editing * Improved function argument hint. * More checkpoints in editor history. * Ctrl-click for jumping to a symbol definition. - * Context help for form editor widgets. - * Goto slot from form editor now works with multiple inheritance. - * Add signal/slot editor to form editor. * Improved open documents view (sorted, single-click, close buttons). * Copying text from the context help browser and output windows didn't work. @@ -36,7 +33,7 @@ Debugging no dumper buildstep anymore. * New dumper for std::set. Improved QString, QVariant, std::wstring * Make strategy to load shared objects configurable (auto-solib-add). - * Maximum stack depth configurable. + * Increase number of shown stack frames on request instead of loading them all. * Improved interaction in the Locals&Watchers view. Wizards @@ -48,6 +45,7 @@ Wizards Designer * Added signal/slot editor. * Fixed "Goto slot" (formatting/multiple inheritance). + * Context help for form editor widgets. Version control plugins * Fixed handling of colored git output. diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index e47ed3eb9b588769ef9e816fc270efdf497f1f19..a59897820a3f760b6c5f25e1c142c7f74dd0584e 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -43,21 +43,6 @@ \endlist \endtable - \raw HTML - <center> - <object width="425" height="344"> - <param name="movie" - value="http://www.youtube.com/v/U7yje3D1UM4&hl=en&fs=1"></param> - <param name="allowFullScreen" value="true"></param> - <param name="allowscriptaccess" value="always"></param> - <embed src="http://www.youtube.com/v/U7yje3D1UM4&hl=en&fs=1" - type="application/x-shockwave-flash" allowscriptaccess="always" - allowfullscreen="true" width="425" height="344"> - </embed> - </object> - </center> - \endraw - To learn more about the Qt Creator, click on one of the links below: \list @@ -1438,23 +1423,6 @@ \title Keyboard Shortcuts - \raw HTML - <center> - <object width="480" height="295"> - <param name="movie" - value="http://www.youtube.com/v/6WGCxLIjRNg&hl=en&fs=1"> - </param> - <param name="allowFullScreen" value="true"></param> - <param name="allowscriptaccess" value="always"></param> - <embed src="http://www.youtube.com/v/6WGCxLIjRNg&hl=en&fs=1" - type="application/x-shockwave-flash" allowscriptaccess="always" - allowfullscreen="true" width="480" height="295"> - </embed> - </object> - </center> - \endraw - - Qt Creator provides various keyboard shortcuts to aid in the development process. These shortcuts are listed in the table below: diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index 80ab420c5fa1e139c7ecac08aa6f59c551accc56..06c1e1ae1cf2f51a609b8f17a83c8732dec85bbe 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -202,11 +202,12 @@ QT_END_NAMESPACE #endif // PRIVATE_OBJECT_ALLOWED -// this can be mangled typenames of nested templates, each char-by-char -// comma-separated integer list -static char qDumpInBuffer[10000]; -static char qDumpOutBuffer[100000]; -//static char qDumpSize[20]; +// This can be mangled typenames of nested templates, each char-by-char +// comma-separated integer list... +Q_DECL_EXPORT char qDumpInBuffer[10000]; + +// The output buffer. +Q_DECL_EXPORT char qDumpOutBuffer[100000]; namespace { @@ -2396,6 +2397,10 @@ static void handleProtocolVersion2and3(QDumper & d) const char *type = stripNamespace(d.outertype); // type[0] is usally 'Q', so don't use it switch (type[1]) { + case 'a': + if (isEqual(type, "map")) + qDumpStdMap(d); + break; case 'B': if (isEqual(type, "QByteArray")) qDumpQByteArray(d); @@ -2406,6 +2411,12 @@ static void handleProtocolVersion2and3(QDumper & d) else if (isEqual(type, "QDir")) qDumpQDir(d); break; + case 'e': + if (isEqual(type, "vector")) + qDumpStdVector(d); + else if (isEqual(type, "set")) + qDumpStdSet(d); + break; case 'F': if (isEqual(type, "QFile")) qDumpQFile(d); @@ -2418,6 +2429,10 @@ static void handleProtocolVersion2and3(QDumper & d) else if (isEqual(type, "QHashNode")) qDumpQHashNode(d); break; + case 'i': + if (isEqual(type, "list")) + qDumpStdList(d); + break; case 'I': if (isEqual(type, "QImage")) qDumpQImage(d); @@ -2510,7 +2525,7 @@ static void handleProtocolVersion2and3(QDumper & d) extern "C" Q_DECL_EXPORT -void qDumpObjectData440( +void *qDumpObjectData440( int protocolVersion, int token, void *data, @@ -2545,18 +2560,18 @@ void qDumpObjectData440( "\""NS"QMap\"," "\""NS"QMapNode\"," "\""NS"QModelIndex\"," - #if QT_VERSION >= 0x040500 +#if QT_VERSION >= 0x040500 "\""NS"QMultiMap\"," - #endif +#endif "\""NS"QObject\"," "\""NS"QObjectMethodList\"," // hack to get nested properties display "\""NS"QObjectPropertyList\"," - #if PRIVATE_OBJECT_ALLOWED +#if PRIVATE_OBJECT_ALLOWED "\""NS"QObjectSignal\"," "\""NS"QObjectSignalList\"," "\""NS"QObjectSlot\"," "\""NS"QObjectSlotList\"," - #endif // PRIVATE_OBJECT_ALLOWED +#endif // PRIVATE_OBJECT_ALLOWED // << "\""NS"QRegion\"," "\""NS"QSet\"," "\""NS"QString\"," @@ -2565,8 +2580,15 @@ void qDumpObjectData440( "\""NS"QVariant\"," "\""NS"QVector\"," "\""NS"QWidget\"," +#ifdef Q_OS_WIN + "\"basic_string\"," + "\"list\"," + "\"map\"," + "\"set\"," "\"string\"," + "\"vector\"," "\"wstring\"," +#endif "\"std::basic_string\"," "\"std::list\"," "\"std::map\"," @@ -2608,4 +2630,5 @@ void qDumpObjectData440( else { qDebug() << "Unsupported protocol version" << protocolVersion; } + return qDumpOutBuffer; } diff --git a/share/qtcreator/runInTerminal.command b/share/qtcreator/runInTerminal.command index 372820c1b110491dff57148375d717eb99a5ba98..3cc5baa050df1db2ae4becc90e7d63a0ce9b2c59 100755 --- a/share/qtcreator/runInTerminal.command +++ b/share/qtcreator/runInTerminal.command @@ -1,11 +1,50 @@ -#!/bin/bash -osascript >/dev/null 2>&1 <<EOF +#! /bin/bash + +### FIXME: +# - currentTab and geometry stuff does not work with macX 10.4 (tiger) +# - -async is always in effect, i.e., synchronous execution is not implemented + +geom= +async= +while test -n "$1"; do + case $1 in + -async) + async=1 + shift;; + -geom) + shift + w=${1%%x*} + y=${1#*x} + h=${y%%+*} + y=${y#*+} + x=${y%%+*} + y=${y#*+} + geom="\ + set number of columns of currentTab to $w + set number of rows of currentTab to $h + set position of windows whose tabs contains currentTab to {$x, $y}" + shift;; + -e) + shift + break;; + *) + echo "Invalid call" >&2 + exit 1;; + esac +done +args= +for i in "$@"; do + i=${i//\\/\\\\\\\\} + i=${i//\"/\\\\\\\"} + i=${i//\$/\\\\\\\$} + i=${i//\`/\\\\\\\`} + args="$args \\\"$i\\\"" +done +osascript <<EOF tell application "Terminal" - do script "$1 $2 +$3 +\"normal $4|\"; exit" + do script "$args; exit" set currentTab to the result - set number of columns of currentTab to $5 - set number of rows of currentTab to $6 - set position of windows whose tabs contains currentTab to {$7, $8} +$geom activate end tell EOF diff --git a/src/libs/utils/consoleprocess.h b/src/libs/utils/consoleprocess.h index 53c69c91af7206d52c76179b50664a18ef4e4d08..6da57e375b9f168bc8a0fb9f8e4a964ec3d182bf 100644 --- a/src/libs/utils/consoleprocess.h +++ b/src/libs/utils/consoleprocess.h @@ -43,10 +43,14 @@ #include <windows.h> QT_BEGIN_NAMESPACE class QWinEventNotifier; -class QTemporaryFile; QT_END_NAMESPACE #endif +QT_BEGIN_NAMESPACE +class QSettings; +class QTemporaryFile; +QT_END_NAMESPACE + namespace Core { namespace Utils { @@ -69,6 +73,13 @@ public: int exitCode() const { return m_appCode; } // This will be the signal number if exitStatus == CrashExit QProcess::ExitStatus exitStatus() const { return m_appStatus; } +#ifdef Q_OS_UNIX + void setSettings(QSettings *settings) { m_settings = settings; } + static QString defaultTerminalEmulator(); + static QString terminalEmulator(const QSettings *settings); + static void setTerminalEmulator(QSettings *settings, const QString &term); +#endif + signals: void processError(const QString &error); // These reflect the state of the actual client process @@ -102,15 +113,16 @@ private: QProcess::ExitStatus m_appStatus; QLocalServer m_stubServer; QLocalSocket *m_stubSocket; + QTemporaryFile *m_tempFile; #ifdef Q_OS_WIN PROCESS_INFORMATION *m_pid; HANDLE m_hInferior; QWinEventNotifier *inferiorFinishedNotifier; QWinEventNotifier *processFinishedNotifier; - QTemporaryFile *m_tempFile; #else QProcess m_process; QByteArray m_stubServerDir; + QSettings *m_settings; #endif }; diff --git a/src/libs/utils/consoleprocess_unix.cpp b/src/libs/utils/consoleprocess_unix.cpp index 2e20ac0c37aca3c6f36eb27a8ef25993e4e48129..a43264b59d021f41647fa371fee22522190a6778 100644 --- a/src/libs/utils/consoleprocess_unix.cpp +++ b/src/libs/utils/consoleprocess_unix.cpp @@ -30,6 +30,8 @@ #include "consoleprocess.h" #include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QSettings> #include <QtCore/QTemporaryFile> #include <QtNetwork/QLocalSocket> @@ -48,6 +50,7 @@ ConsoleProcess::ConsoleProcess(QObject *parent) m_debug = false; m_appPid = 0; m_stubSocket = 0; + m_settings = 0; connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable())); @@ -72,8 +75,24 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) return false; } - QStringList xtermArgs; - xtermArgs << "-e" + if (!environment().isEmpty()) { + m_tempFile = new QTemporaryFile(); + if (!m_tempFile->open()) { + stubServerShutdown(); + emit processError(tr("Cannot create temp file: %1").arg(m_tempFile->errorString())); + delete m_tempFile; + m_tempFile = 0; + return false; + } + foreach (const QString &var, environment()) { + m_tempFile->write(var.toLocal8Bit()); + m_tempFile->write("", 1); + } + m_tempFile->flush(); + } + + QStringList xtermArgs = terminalEmulator(m_settings).split(QLatin1Char(' ')); // FIXME: quoting + xtermArgs #ifdef Q_OS_MAC << (QCoreApplication::applicationDirPath() + "/../Resources/qtcreator_process_stub") #else @@ -82,13 +101,17 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args) << (m_debug ? "debug" : "exec") << m_stubServer.fullServerName() << tr("Press <RETURN> to close this window...") - << workingDirectory() << environment() << "" + << workingDirectory() + << (m_tempFile ? m_tempFile->fileName() : 0) << program << args; - m_process.start(QLatin1String("xterm"), xtermArgs); + QString xterm = xtermArgs.takeFirst(); + m_process.start(xterm, xtermArgs); if (!m_process.waitForStarted()) { stubServerShutdown(); - emit processError(tr("Cannot start console emulator xterm.")); + emit processError(tr("Cannot start terminal emulator %1.").arg(xterm)); + delete m_tempFile; + m_tempFile = 0; return false; } m_executable = program; @@ -173,6 +196,10 @@ void ConsoleProcess::readStubOutput() emit processError(tr("Cannot execute %1: %2") .arg(m_executable, errorMsg(out.mid(9).toInt()))); } else if (out.startsWith("pid ")) { + // Will not need it any more + delete m_tempFile; + m_tempFile = 0; + m_appPid = out.mid(4).toInt(); emit processStarted(); } else if (out.startsWith("exit ")) { @@ -199,6 +226,8 @@ void ConsoleProcess::stubExited() if (m_stubSocket && m_stubSocket->state() == QLocalSocket::ConnectedState) m_stubSocket->waitForDisconnected(); stubServerShutdown(); + delete m_tempFile; + m_tempFile = 0; if (m_appPid) { m_appStatus = QProcess::CrashExit; m_appCode = -1; @@ -207,3 +236,27 @@ void ConsoleProcess::stubExited() } emit wrapperStopped(); } + +QString ConsoleProcess::defaultTerminalEmulator() +{ +// FIXME: enable this once runInTerminal works nicely +#if 0 //def Q_OS_MAC + return QDir::cleanPath(QCoreApplication::applicationDirPath() + + QLatin1String("/../Resources/runInTerminal.command")); +#else + return QLatin1String("xterm"); +#endif +} + +QString ConsoleProcess::terminalEmulator(const QSettings *settings) +{ + QString dflt = defaultTerminalEmulator() + QLatin1String(" -e"); + if (!settings) + return dflt; + return settings->value(QLatin1String("General/TerminalEmulator"), dflt).toString(); +} + +void ConsoleProcess::setTerminalEmulator(QSettings *settings, const QString &term) +{ + return settings->setValue(QLatin1String("General/TerminalEmulator"), term); +} diff --git a/src/libs/utils/process_stub_unix.c b/src/libs/utils/process_stub_unix.c index 92c38bb5f0d30070ee1ff43339250a0b259327d0..9a3194038215f48d5ff99a767ed612dcf012651b 100644 --- a/src/libs/utils/process_stub_unix.c +++ b/src/libs/utils/process_stub_unix.c @@ -73,18 +73,19 @@ enum { ArgSocket, ArgMsg, ArgDir, - ArgEnv + ArgEnv, + ArgExe }; -/* syntax: $0 {"run"|"debug"} <pid-socket> <continuation-msg> <workdir> <env...> "" <exe> <args...> */ +/* syntax: $0 {"run"|"debug"} <pid-socket> <continuation-msg> <workdir> <env-file> <exe> <args...> */ /* exit codes: 0 = ok, 1 = invocation error, 3 = internal error */ int main(int argc, char *argv[]) { - int envIdx = ArgEnv; int errNo; int chldPid; int chldStatus; int chldPipe[2]; + char **env = 0; struct sockaddr_un sau; if (argc < ArgEnv) { @@ -111,6 +112,35 @@ int main(int argc, char *argv[]) return 1; } + if (*argv[ArgEnv]) { + FILE *envFd; + char *envdata, *edp; + long size; + int count; + if (!(envFd = fopen(argv[ArgEnv], "r"))) { + fprintf(stderr, "Cannot read creator env file %s: %s\n", + argv[ArgEnv], strerror(errno)); + doExit(1); + } + fseek(envFd, 0, SEEK_END); + size = ftell(envFd); + rewind(envFd); + envdata = malloc(size); + if (fread(envdata, 1, size, envFd) != (size_t)size) { + perror("Failed to read env file"); + doExit(1); + } + fclose(envFd); + for (count = 0, edp = envdata; edp < envdata + size; ++count) + edp += strlen(edp) + 1; + env = malloc((count + 1) * sizeof(char *)); + for (count = 0, edp = envdata; edp < envdata + size; ++count) { + env[count] = edp; + edp += strlen(edp) + 1; + } + env[count] = 0; + } + /* Create execution result notification pipe. */ if (pipe(chldPipe)) { perror("Cannot create status pipe"); @@ -142,14 +172,10 @@ int main(int argc, char *argv[]) ptrace(PT_TRACE_ME, 0, 0, 0); #endif - for (envIdx = ArgEnv; *argv[envIdx]; ++envIdx) ; - if (envIdx != ArgEnv) { - argv[envIdx] = 0; - environ = argv + ArgEnv; - } - ++envIdx; + if (env) + environ = env; - execvp(argv[envIdx], argv + envIdx); + execvp(argv[ArgExe], argv + ArgExe); /* Only expected error: no such file or direcotry, i.e. executable not found */ errNo = errno; write(chldPipe[1], &errNo, sizeof(errNo)); /* Only realistic error case is SIGPIPE */ diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index dbfcc44c801355fc10131b13710796e41cc6f400..f9b2cde57b2734c2cb32fd9904ecbae36775f958 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -49,6 +49,7 @@ #include <extensionsystem/pluginmanager.h> +#include <utils/consoleprocess.h> #include <utils/qtcassert.h> #include <QtCore/QDebug> @@ -73,6 +74,7 @@ Q_DECLARE_METATYPE(Core::IEditor*) using namespace Core; using namespace Core::Internal; +using namespace Core::Utils; enum { debugEditorManager=0 }; @@ -429,15 +431,14 @@ void EditorManager::init() QString EditorManager::defaultExternalEditor() const { -#ifdef Q_OS_MAC - return m_d->m_core->resourcePath() - +QLatin1String("/runInTerminal.command vi %f %l %c %W %H %x %y"); -#elif defined(Q_OS_UNIX) - return QLatin1String("xterm -geom %Wx%H+%x+%y -e vi %f +%l +\"normal %c|\""); -#elif defined (Q_OS_WIN) - return QLatin1String("notepad %f"); +#ifdef Q_OS_UNIX + return ConsoleProcess::defaultTerminalEmulator() + QLatin1String( +# ifdef Q_OS_MAC + " -async" +# endif + " -geom %Wx%H+%x+%y -e vi %f +%l +\"normal %c|\""); #else - return QString(); + return QLatin1String("notepad %f"); #endif } @@ -462,7 +463,7 @@ void EditorManager::removeEditor(IEditor *editor) } -void EditorManager::handleContextChange(IContext *context) +void EditorManager::handleContextChange(Core::IContext *context) { if (debugEditorManager) qDebug() << Q_FUNC_INFO; @@ -1172,9 +1173,8 @@ bool EditorManager::saveFile(IEditor *editor) return true; } - if (file->isReadOnly() || fileName.isEmpty()) { + if (file->isReadOnly() || fileName.isEmpty()) return saveFileAs(editor); - } m_d->m_core->fileManager()->blockFileChange(file); const bool success = file->save(fileName); diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp index b996ed50407337bd9bc830a4dbbf64f410875203..a13c72accc3147fcd12d987b484bc6a8dc1aea4d 100644 --- a/src/plugins/coreplugin/filemanager.cpp +++ b/src/plugins/coreplugin/filemanager.cpp @@ -453,7 +453,7 @@ void FileManager::changedFile(const QString &file) foreach (IFile *fileinterface, managedFiles(file)) m_changedFiles << fileinterface; if (wasempty && !m_changedFiles.isEmpty()) { - QTimer::singleShot (200, this, SLOT(checkForReload())); + QTimer::singleShot(200, this, SLOT(checkForReload())); } } diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 969599b2d8a9140341aed96ec2f3691e7e04596f..ff0f73f330275fc13e35e2a2d292e9e26cf555bc 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -31,11 +31,14 @@ #include "stylehelper.h" #include "utils/qtcolorbutton.h" +#include <utils/consoleprocess.h> #include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/icore.h> #include <QtGui/QMessageBox> #include "ui_generalsettings.h" +using namespace Core::Utils; using namespace Core::Internal; GeneralSettings::GeneralSettings(): @@ -71,6 +74,13 @@ QWidget *GeneralSettings::createPage(QWidget *parent) m_page->colorButton->setColor(StyleHelper::baseColor()); m_page->externalEditorEdit->setText(EditorManager::instance()->externalEditor()); +#ifdef Q_OS_UNIX + m_page->terminalEdit->setText(ConsoleProcess::terminalEmulator(Core::ICore::instance()->settings())); +#else + m_page->terminalLabel->hide(); + m_page->terminalEdit->hide(); + m_page->resetTerminalButton->hide(); +#endif connect(m_page->resetButton, SIGNAL(clicked()), this, SLOT(resetInterfaceColor())); @@ -78,6 +88,10 @@ QWidget *GeneralSettings::createPage(QWidget *parent) this, SLOT(resetExternalEditor())); connect(m_page->helpExternalEditorButton, SIGNAL(clicked()), this, SLOT(showHelpForExternalEditor())); +#ifdef Q_OS_UNIX + connect(m_page->resetTerminalButton, SIGNAL(clicked()), + this, SLOT(resetTerminal())); +#endif return w; } @@ -87,6 +101,10 @@ void GeneralSettings::apply() // Apply the new base color if accepted StyleHelper::setBaseColor(m_page->colorButton->color()); EditorManager::instance()->setExternalEditor(m_page->externalEditorEdit->text()); +#ifdef Q_OS_UNIX + ConsoleProcess::setTerminalEmulator(Core::ICore::instance()->settings(), + m_page->terminalEdit->text()); +#endif } void GeneralSettings::finish() @@ -104,6 +122,13 @@ void GeneralSettings::resetExternalEditor() m_page->externalEditorEdit->setText(EditorManager::instance()->defaultExternalEditor()); } +#ifdef Q_OS_UNIX +void GeneralSettings::resetTerminal() +{ + m_page->terminalEdit->setText(ConsoleProcess::defaultTerminalEmulator() + QLatin1String(" -e")); +} +#endif + void GeneralSettings::showHelpForExternalEditor() { if (m_dialog) { diff --git a/src/plugins/coreplugin/generalsettings.h b/src/plugins/coreplugin/generalsettings.h index 9135df7f4a303e5c41a3f54492c2dd3f5fee77e6..d75cd2d8a3938d805044b9ff149e4569d15aed03 100644 --- a/src/plugins/coreplugin/generalsettings.h +++ b/src/plugins/coreplugin/generalsettings.h @@ -59,6 +59,9 @@ private slots: void resetInterfaceColor(); void resetExternalEditor(); void showHelpForExternalEditor(); +#ifdef Q_OS_UNIX + void resetTerminal(); +#endif private: Ui_GeneralSettings *m_page; diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui index c014fae607b8a6585a8b966abeadb117573bff85..826c45ae6bc0d32a0cf05a10d3e9d53abd84761a 100644 --- a/src/plugins/coreplugin/generalsettings.ui +++ b/src/plugins/coreplugin/generalsettings.ui @@ -96,6 +96,34 @@ </item> </layout> </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="terminalLabel"> + <property name="text"> + <string>Terminal:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="terminalEdit"/> + </item> + <item> + <widget class="QToolButton" name="resetTerminalButton"> + <property name="toolTip"> + <string>Reset to default</string> + </property> + <property name="text"> + <string>R</string> + </property> + <property name="icon"> + <iconset resource="core.qrc"> + <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset> + </property> + </widget> + </item> + </layout> + </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_5"> <item> diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 543111816b1588c25f40c785279d7bf66cba5c7e..446b7544bb3dc4381f316ccbed50459aceeff4fc 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -1070,11 +1070,14 @@ static const char *settingsGroup = "MainWindow"; static const char *geometryKey = "Geometry"; static const char *colorKey = "Color"; static const char *maxKey = "Maximized"; +static const char *fullScreenKey = "FullScreen"; void MainWindow::readSettings() { m_settings->beginGroup(QLatin1String(settingsGroup)); + StyleHelper::setBaseColor(m_settings->value(QLatin1String(colorKey)).value<QColor>()); + const QVariant geom = m_settings->value(QLatin1String(geometryKey)); if (geom.isValid()) { setGeometry(geom.toRect()); @@ -1083,8 +1086,10 @@ void MainWindow::readSettings() } if (m_settings->value(QLatin1String(maxKey), false).toBool()) setWindowState(Qt::WindowMaximized); + setFullScreen(m_settings->value(QLatin1String(fullScreenKey), false).toBool()); m_settings->endGroup(); + m_editorManager->readSettings(m_settings); m_navigationWidget->restoreSettings(m_settings); m_rightPaneWidget->readSettings(m_settings); @@ -1093,14 +1098,18 @@ void MainWindow::readSettings() void MainWindow::writeSettings() { m_settings->beginGroup(QLatin1String(settingsGroup)); - m_settings->setValue(colorKey, StyleHelper::baseColor()); - const QString maxSettingsKey = QLatin1String(maxKey); - if (windowState() & Qt::WindowMaximized) { - m_settings->setValue(maxSettingsKey, true); + + m_settings->setValue(QLatin1String(colorKey), StyleHelper::baseColor()); + + if (windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) { + m_settings->setValue(QLatin1String(maxKey), (bool) (windowState() & Qt::WindowMaximized)); + m_settings->setValue(QLatin1String(fullScreenKey), (bool) (windowState() & Qt::WindowFullScreen)); } else { - m_settings->setValue(maxSettingsKey, false); + m_settings->setValue(QLatin1String(maxKey), false); + m_settings->setValue(QLatin1String(fullScreenKey), false); m_settings->setValue(QLatin1String(geometryKey), geometry()); } + m_settings->endGroup(); m_fileManager->saveRecentFiles(); @@ -1209,7 +1218,7 @@ QPrinter *MainWindow::printer() const { if (!m_printer) m_printer = new QPrinter(QPrinter::HighResolution); - return m_printer; + return m_printer; } void MainWindow::setFullScreen(bool on) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 6ade9b34fde2652d6e21e9207c04529ea66fdc4e..7a6ff93fbc6e73cd00395a1806dba9315eea7c02 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -250,6 +250,7 @@ DebuggerSettings *DebuggerSettings::instance() // item = new SavedAction(instance); item->setSettingsKey(debugModeGroup, QLatin1String("Location")); + item->setDefaultValue("gdb"); instance->insertItem(GdbLocation, item); item = new SavedAction(instance); @@ -272,11 +273,6 @@ DebuggerSettings *DebuggerSettings::instance() item->setCheckable(true); instance->insertItem(UseToolTips, item); - item = new SavedAction(instance); - item->setDefaultValue(QLatin1String("xterm")); - item->setSettingsKey(debugModeGroup, QLatin1String("Terminal")); - instance->insertItem(TerminalApplication, item); - item = new SavedAction(instance); item->setSettingsKey(debugModeGroup, QLatin1String("ListSourceFiles")); item->setText(tr("List source files")); @@ -291,6 +287,7 @@ DebuggerSettings *DebuggerSettings::instance() item = new SavedAction(instance); item->setSettingsKey(debugModeGroup, QLatin1String("AllPluginBreakpoints")); + item->setDefaultValue(true); instance->insertItem(AllPluginBreakpoints, item); item = new SavedAction(instance); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 6fc9366f7bf6ce9dd733f0de28e549132b85f9e4..0a43ffa91eef575b164a4a9e213e3a8089b0d78a 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -77,7 +77,6 @@ enum DebuggerActionCode AdjustColumnWidths, AlwaysAdjustColumnWidths, AutoQuit, - TerminalApplication, LockView, // Gdb diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index c4c517327e72d05e162974a72163f00669a6e771..483ad82a1e6627e5bad0cc72de0ee72d77a1adfa 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -131,7 +131,7 @@ AttachCoreDialog::AttachCoreDialog(QWidget *parent) m_ui->execFileName->setPromptDialogTitle(tr("Select Executable")); m_ui->coreFileName->setExpectedKind(Core::Utils::PathChooser::File); - m_ui->coreFileName->setPromptDialogTitle(tr("Select Executable")); + m_ui->coreFileName->setPromptDialogTitle(tr("Select Core File")); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 90cb7bd1f790047bb6626f159e692aa229488992..4d88db88c3a27f5dc24008cef677dce683fec616 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -269,8 +269,6 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) m_ui.gdbLocationChooser->setPromptDialogTitle(tr("Choose Gdb Location")); m_ui.scriptFileChooser->setExpectedKind(Core::Utils::PathChooser::File); m_ui.scriptFileChooser->setPromptDialogTitle(tr("Choose Location of Startup Script File")); - m_ui.terminalChooser->setExpectedKind(Core::Utils::PathChooser::Command); - m_ui.terminalChooser->setPromptDialogTitle(tr("Choose Location of Terminal Application")); m_group.clear(); m_group.insert(theDebuggerAction(GdbLocation), @@ -279,8 +277,6 @@ QWidget *GdbOptionPage::createPage(QWidget *parent) m_ui.scriptFileChooser); m_group.insert(theDebuggerAction(GdbEnvironment), m_ui.environmentEdit); - m_group.insert(theDebuggerAction(TerminalApplication), - m_ui.terminalChooser); m_group.insert(theDebuggerAction(AllPluginBreakpoints), m_ui.radioButtonAllPluginBreakpoints); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 0279c15181f724f4559f09a68dbe444fd222f52d..0e161f107955320634e1b7fb342a27947ead62e6 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -163,6 +163,20 @@ static int ¤tToken() return token; } +static bool isSkippable(int type) +{ + return type == RegisterListValues + && type == StackListThreads + && type == StackListFrames + && type == StackListLocals + && type == StackListArguments + && type == WatchVarAssign + && type == WatchVarListChildren + && type == WatchVarCreate + && type == WatchEvaluateExpression + && type == WatchToolTip; +} + /////////////////////////////////////////////////////////////////////// // // GdbEngine @@ -667,7 +681,7 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record) GdbCookie cmd = m_cookieForToken.take(token); - if (record.token < m_oldestAcceptableToken) { + if (record.token < m_oldestAcceptableToken && isSkippable(cmd.type)) { //qDebug() << "### SKIPPING OLD RESULT " << record.toString(); //QMessageBox::information(m_mainWindow, tr("Skipped"), "xxx"); return; @@ -1140,9 +1154,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) + data.findChild("signal-name").toString(); } q->showStatusMessage(msg); - // FIXME: shouldn't this use a statis change? - debugMessage("CALLING PARENT EXITDEBUGGER"); - q->exitDebugger(); + sendCommand("-gdb-exit"); return; } @@ -1857,8 +1869,21 @@ void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber) void GdbEngine::setTokenBarrier() { - foreach (const GdbCookie &ck, m_cookieForToken) - QTC_ASSERT(ck.synchronized || ck.type == GdbInvalidCommand, return); + foreach (const GdbCookie &cookie, m_cookieForToken) { + QTC_ASSERT( + cookie.synchronized + || cookie.type == GdbInvalidCommand + // FIXME: use something like "command classes" for these cases: + || cookie.type == GdbInfoProc + || cookie.type == GdbStubAttached + || cookie.type == ModulesList + || cookie.type == WatchDebuggingHelperSetup + || cookie.type == GdbQueryDebuggingHelper, + qDebug() << "CMD: " << cookie.command << "TYPE: " << cookie.type + << "SYNC: " << cookie.synchronized; + return + ); + } PENDING_DEBUG("\n--- token barrier ---\n"); emit gdbInputAvailable(QString(), "--- token barrier ---"); m_oldestAcceptableToken = currentToken(); @@ -1930,7 +1955,10 @@ void GdbEngine::breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt if (pos > 0) { data->bpLineNumber = child.data().mid(pos + 1); data->markerLineNumber = child.data().mid(pos + 1).toInt(); - files.prepend(child.data().left(pos)); + QString file = child.data().left(pos); + if (file.startsWith('"') && file.endsWith('"')) + file = file.mid(1, file.size() - 2); + files.prepend(file); } else { files.prepend(child.data()); } @@ -1978,7 +2006,7 @@ void GdbEngine::sendInsertBreakpoint(int index) // set up fallback in case of pending breakpoints which aren't handled // by the MI interface #ifdef Q_OS_LINUX - QString cmd = "-break-insert "; + QString cmd = "-break-insert -f "; //if (!data->condition.isEmpty()) // cmd += "-c " + data->condition + " "; cmd += where; @@ -2133,6 +2161,8 @@ void GdbEngine::handleBreakInsert(const GdbResultRecord &record, int index) // + data->lineNumber + "\""; QString where = "\"" + data->fileName + "\":" + data->lineNumber; + // Should not happen with -break-insert -f. gdb older than 6.8? + QTC_ASSERT(false, /**/); sendCommand("break " + where, BreakInsert1, index); #endif #ifdef Q_OS_MAC @@ -3054,7 +3084,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) } else if (outertype == m_namespace + "QMapNode") { extraArgs[2] = sizeofTypeExpression(data.type); extraArgs[3] = "(size_t)&(('" + data.type + "'*)0)->value"; - } else if (outertype == "std::vector") { + } else if (outertype == "std::vector" || outertype == "vector") { //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners; if (inners.at(0) == "bool") { outertype = "std::vector::bool"; @@ -3062,18 +3092,18 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) //extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); //extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; } - } else if (outertype == "std::deque") { + } else if (outertype == "std::deque" || outertype == "deque") { // remove 'std::allocator<...>': extraArgs[1] = "0"; - } else if (outertype == "std::stack") { + } else if (outertype == "std::stack" || outertype == "stack") { // remove 'std::allocator<...>': extraArgs[1] = "0"; - } else if (outertype == "std::set") { + } else if (outertype == "std::set" || outertype == "set") { // remove 'std::less<...>': extraArgs[1] = "0"; // remove 'std::allocator<...>': extraArgs[2] = "0"; - } else if (outertype == "std::map") { + } else if (outertype == "std::map" || outertype == "map") { // We don't want the comparator and the allocator confuse gdb. // But we need the offset of the second item in the value pair. // We read the type of the pair from the allocator argument because @@ -3084,7 +3114,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren) pairType = pairType.mid(15, pairType.size() - 15 - 2); extraArgs[2] = "(size_t)&(('" + pairType + "'*)0)->second"; extraArgs[3] = "0"; - } else if (outertype == "std::basic_string") { + } else if (outertype == "std::basic_string" || outertype == "basic_string") { //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners; if (inners.at(0) == "char") { outertype = "std::string"; @@ -4148,10 +4178,10 @@ void GdbEngine::tryLoadDebuggingHelpers() QString flag = QString::number(RTLD_NOW); sendCommand("sharedlibrary libc"); // for malloc sendCommand("sharedlibrary libdl"); // for dlopen - sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")", + sendCommand("call (void*)dlopen(\"" + lib + "\", " + flag + ")", WatchDebuggingHelperSetup); // some older systems like CentOS 4.6 prefer this: - sendCommand("call (void)__dlopen(\"" + lib + "\", " + flag + ")", + sendCommand("call (void*)__dlopen(\"" + lib + "\", " + flag + ")", WatchDebuggingHelperSetup); sendCommand("sharedlibrary " + dotEscape(lib)); #endif diff --git a/src/plugins/debugger/gdboptionpage.ui b/src/plugins/debugger/gdboptionpage.ui index c3994e7b8e948d08a46a6d3435fd0cbd9da03646..baf91e4667dbf2832e5216b7d4fd6a43e2a54f77 100644 --- a/src/plugins/debugger/gdboptionpage.ui +++ b/src/plugins/debugger/gdboptionpage.ui @@ -39,17 +39,6 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QLabel" name="terminalLocation"> - <property name="toolTip"> - <string>This is either a full abolute path leading to the terminal -you indent to use or the name of a terminal that will be searched in your PATH.</string> - </property> - <property name="text"> - <string>Terminal:</string> - </property> - </widget> - </item> <item row="1" column="0"> <widget class="QLabel" name="labelEnvironment"> <property name="text"> @@ -76,9 +65,6 @@ you indent to use or the name of a terminal that will be searched in your PATH.< <item row="0" column="1"> <widget class="Core::Utils::PathChooser" name="gdbLocationChooser" native="true"/> </item> - <item row="3" column="1"> - <widget class="Core::Utils::PathChooser" name="terminalChooser" native="true"/> - </item> </layout> </widget> </item> diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 9ccfb791d624198cae8e2de1a2506afb9d9f15d2..42e42f5f0b6dbfbdbf9058128287fce22a3d7ab0 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -66,6 +66,8 @@ using namespace Debugger::Internal; static const QString strNotInScope = QLatin1String("<not in scope>"); +static int watcherCounter = 0; + //////////////////////////////////////////////////////////////////// // // WatchData @@ -356,54 +358,101 @@ WatchHandler::WatchHandler() SIGNAL(triggered()), this, SLOT(collapseChildren())); } +static QString chopConst(QString type) +{ + while (1) { + if (type.startsWith("const")) + type = type.mid(5); + else if (type.startsWith(' ')) + type = type.mid(1); + else if (type.endsWith("const")) + type.chop(5); + else if (type.endsWith(' ')) + type.chop(1); + else + break; + } + return type; +} + static QString niceType(QString type) { if (type.contains(QLatin1String("std::"))) { // std::string - type.replace(QLatin1String("std::basic_string<char, std::char_traits<char>, " - "std::allocator<char> >"), QLatin1String("std::string")); + type.replace(QLatin1String("basic_string<char, std::char_traits<char>, " + "std::allocator<char> >"), QLatin1String("string")); // std::wstring - type.replace(QLatin1String("std::basic_string<wchar_t, std::char_traits<wchar_t>, " - "std::allocator<wchar_t> >"), QLatin1String("std::wstring")); + type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, " + "std::allocator<wchar_t> >"), QLatin1String("wstring")); // std::vector - static QRegExp re1(QLatin1String("std::vector<(.*), std::allocator<(.*)>\\s*>")); + static QRegExp re1(QLatin1String("vector<(.*), std::allocator<(.*)>\\s*>")); re1.setMinimal(true); for (int i = 0; i != 10; ++i) { if (re1.indexIn(type) == -1 || re1.cap(1) != re1.cap(2)) break; - type.replace(re1.cap(0), QLatin1String("std::vector<") + re1.cap(1) + QLatin1Char('>')); + type.replace(re1.cap(0), QLatin1String("vector<") + re1.cap(1) + QLatin1Char('>')); + } + + // std::deque + static QRegExp re5(QLatin1String("deque<(.*), std::allocator<(.*)>\\s*>")); + re5.setMinimal(true); + for (int i = 0; i != 10; ++i) { + if (re5.indexIn(type) == -1 || re5.cap(1) != re5.cap(2)) + break; + type.replace(re5.cap(0), QLatin1String("deque<") + re5.cap(1) + QLatin1Char('>')); + } + + // std::stack + static QRegExp re6(QLatin1String("stack<(.*), std::deque<(.*), std::allocator<(.*)>\\s*> >")); + re6.setMinimal(true); + for (int i = 0; i != 10; ++i) { + if (re6.indexIn(type) == -1 || re6.cap(1) != re6.cap(2) + || re6.cap(1) != re6.cap(2)) + break; + type.replace(re6.cap(0), QLatin1String("stack<") + re6.cap(1) + QLatin1Char('>')); } // std::list - static QRegExp re2(QLatin1String("std::list<(.*), std::allocator<(.*)>\\s*>")); + static QRegExp re2(QLatin1String("list<(.*), std::allocator<(.*)>\\s*>")); re2.setMinimal(true); for (int i = 0; i != 10; ++i) { if (re2.indexIn(type) == -1 || re2.cap(1) != re2.cap(2)) break; - type.replace(re2.cap(0), QLatin1String("std::list<") + re2.cap(1) + QLatin1Char('>')); + type.replace(re2.cap(0), QLatin1String("list<") + re2.cap(1) + QLatin1Char('>')); } // std::map - static QRegExp re3(QLatin1String("std::map<(.*), (.*), std::less<(.*)\\s*>, " - "std::allocator<std::pair<const (.*), (.*)\\s*> > >")); - re3.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re3.indexIn(type) == -1 || re3.cap(1) != re3.cap(3) - || re3.cap(1) != re3.cap(4) || re3.cap(2) != re3.cap(5)) - break; - type.replace(re3.cap(0), QLatin1String("std::map<") + re3.cap(1) + QLatin1String(", ") + re3.cap(2) + QLatin1Char('>')); + { + static QRegExp re(QLatin1String("map<(.*), (.*), std::less<(.*)>, " + "std::allocator<std::pair<(.*), (.*)> > >")); + re.setMinimal(true); + for (int i = 0; i != 10; ++i) { + if (re.indexIn(type) == -1) + break; + QString key = chopConst(re.cap(1)); + QString value = chopConst(re.cap(2)); + QString key1 = chopConst(re.cap(3)); + QString key2 = chopConst(re.cap(4)); + QString value2 = chopConst(re.cap(5)); + if (value != value2 || key != key1 || key != key2) { + qDebug() << key << key1 << key2 << value << value2 + << (key == key1) << (key == key2) << (value == value2); + break; + } + type.replace(re.cap(0), QString("map<%1, %2>").arg(key).arg(value)); + } } // std::set - static QRegExp re4(QLatin1String("std::set<(.*), std::less<(.*)>, std::allocator<(.*)>\\s*>")); + static QRegExp re4(QLatin1String("set<(.*), std::less<(.*)>, std::allocator<(.*)>\\s*>")); re1.setMinimal(true); for (int i = 0; i != 10; ++i) { if (re4.indexIn(type) == -1 || re4.cap(1) != re4.cap(2) || re4.cap(1) != re4.cap(3)) break; - type.replace(re4.cap(0), QLatin1String("std::set<") + re4.cap(1) + QLatin1Char('>')); + type.replace(re4.cap(0), QLatin1String("set<") + re4.cap(1) + QLatin1Char('>')); } type.replace(QLatin1String(" >"), QString(QLatin1Char('>'))); @@ -875,17 +924,21 @@ void WatchHandler::watchExpression() watchExpression(action->data().toString()); } +QString WatchHandler::watcherName(const QString &exp) +{ + return QLatin1String("watch.") + QString::number(m_watchers[exp]); +} + void WatchHandler::watchExpression(const QString &exp) { // FIXME: 'exp' can contain illegal characters //MODEL_DEBUG("WATCH: " << exp); - static int counter = 0; + m_watchers[exp] = watcherCounter++; WatchData data; data.exp = exp; data.name = exp; - data.iname = QLatin1String("watch.") + QString::number(counter++); + data.iname = watcherName(exp); insertData(data); - m_watchers.append(exp); saveWatchers(); emit watchModelUpdateRequested(); } @@ -970,7 +1023,7 @@ void WatchHandler::removeWatchExpression() void WatchHandler::removeWatchExpression(const QString &exp) { MODEL_DEBUG("REMOVE WATCH: " << exp); - m_watchers.removeOne(exp); + m_watchers.remove(exp); for (int i = m_completeSet.size(); --i >= 0;) { const WatchData & data = m_completeSet.at(i); if (data.iname.startsWith(QLatin1String("watch.")) && data.exp == exp) { @@ -994,8 +1047,9 @@ void WatchHandler::reinitializeWatchersHelper() { // copy over all watchers and mark all watchers as incomplete int i = 0; - foreach (const QString &exp, m_watchers) { + foreach (const QString &exp, m_watchers.keys()) { WatchData data; + data.iname = watcherName(exp); data.level = -1; data.row = -1; data.parentIndex = -1; @@ -1205,15 +1259,16 @@ void WatchHandler::loadWatchers() { QVariant value; sessionValueRequested("Watchers", &value); - m_watchers = value.toStringList(); + foreach (const QString &exp, value.toStringList()) + m_watchers[exp] = watcherCounter++; //qDebug() << "LOAD WATCHERS: " << m_watchers; reinitializeWatchersHelper(); } void WatchHandler::saveWatchers() { - //qDebug() << "SAVE WATCHERS: " << m_watchers; - setSessionValueRequested("Watchers", m_watchers); + //qDebug() << "SAVE WATCHERS: " << m_watchers.keys(); + setSessionValueRequested("Watchers", QVariant(m_watchers.keys())); } void WatchHandler::saveSessionData() diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 3f773ac1df37923c8ea6f525654d88d98b9fb4c9..13f37dabf49c2a1cb1d6a206bdb708c78a1fa3dd 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -216,7 +216,8 @@ private: QList<WatchData> m_completeSet; QList<WatchData> m_oldSet; QList<WatchData> m_displaySet; - QStringList m_watchers; + QHash<QString, int> m_watchers; + QString watcherName(const QString &exp); void setDisplayedIName(const QString &iname, bool on); QSet<QString> m_expandedINames; // those expanded in the treeview diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index 0b76cfc1de662a414fc571fc56880cba49d42593..cc6e580a8f53bdbfbfe7d7c494b740882d6d7183 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -50,6 +50,7 @@ #include <utils/qtcassert.h> + #include <QtCore/QDebug> #include <QtCore/QFile> #include <QtCore/QObject> @@ -606,22 +607,28 @@ EventResult FakeVimHandler::Private::handleKey(int key, int unmodified, void FakeVimHandler::Private::moveDown(int n) { - // m_tc.movePosition(Down, MoveAnchor, n); does not work for "hidden" - // documents like in the autotests - const QTextBlock &block = m_tc.block(); - const int col = m_tc.position() - block.position(); - const int line = block.blockNumber(); - const int pos = m_tc.document()->findBlockByNumber(line + n).position(); - setPosition(pos + qMin(block.length(), col)); - setPosition(pos); +#if 0 + // does not work for "hidden" documents like in the autotests + 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 pos = block.position(); + setPosition(pos + qMin(block.length() - 1, col)); + moveToTargetColumn(); +#endif } void FakeVimHandler::Private::moveToEndOfLine() { - // m_tc.movePosition(EndOfLine, MoveAnchor) does not work for "hidden" - // documents like in the autotests +#if 0 + // does not work for "hidden" documents like in the autotests + m_tc.movePosition(EndOfLine, MoveAnchor); +#else const QTextBlock &block = m_tc.block(); setPosition(block.position() + block.length() - 1); +#endif } void FakeVimHandler::Private::finishMovement(const QString &dotCommand) @@ -1668,7 +1675,6 @@ void FakeVimHandler::Private::selectRange(int beginLine, int endLine) void FakeVimHandler::Private::handleCommand(const QString &cmd) { m_tc = EDITOR(textCursor()); - init(); handleExCommand(cmd); EDITOR(setTextCursor(m_tc)); } @@ -2077,12 +2083,22 @@ void FakeVimHandler::Private::shiftRegionLeft(int repeat) void FakeVimHandler::Private::moveToTargetColumn() { - if (m_targetColumn == -1 || m_tc.block().length() <= m_targetColumn) - m_tc.movePosition(EndOfLine, KeepAnchor); - else + if (m_targetColumn == -1 || m_tc.block().length() <= m_targetColumn) { + const QTextBlock &block = m_tc.block(); + m_tc.setPosition(block.position() + block.length() - 1, KeepAnchor); + } else { m_tc.setPosition(m_tc.block().position() + m_targetColumn, KeepAnchor); + } } +/* if simple is given: + * class 0: spaces + * class 1: non-spaces + * else + * class 0: spaces + * class 1: non-space-or-letter-or-number + * class 2: letter-or-number + */ static int charClass(QChar c, bool simple) { if (simple) @@ -2100,6 +2116,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(); int thisClass = charClass(c, simple); if (thisClass != lastClass && lastClass != 0) --repeat; @@ -2110,6 +2127,7 @@ void FakeVimHandler::Private::moveToWordBoundary(bool simple, bool forward) break; forward ? moveRight() : moveLeft(); } + setTargetColumn(); } void FakeVimHandler::Private::handleFfTt(int key) @@ -2145,6 +2163,7 @@ void FakeVimHandler::Private::handleFfTt(int key) break; } } + setTargetColumn(); } void FakeVimHandler::Private::moveToNextWord(bool simple) @@ -2165,6 +2184,7 @@ void FakeVimHandler::Private::moveToNextWord(bool simple) if (m_tc.position() == n) break; } + setTargetColumn(); } void FakeVimHandler::Private::moveToMatchingParanthesis() @@ -2178,6 +2198,7 @@ void FakeVimHandler::Private::moveToMatchingParanthesis() if (m_submode == NoSubMode || m_submode == ZSubMode || m_submode == RegisterSubMode) m_tc.movePosition(Left, KeepAnchor, 1); } + setTargetColumn(); } int FakeVimHandler::Private::cursorLineOnScreen() const diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 7f4e3eeada78a80f6ab345ef21e788dbda7be304..0ab92d82639b9d66cc911c6e6b525c1eb766432a 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -543,7 +543,7 @@ void FakeVimPluginPrivate::indentRegion(int *amount, int beginLine, int endLine, void FakeVimPluginPrivate::quitFakeVim() { - setUseFakeVim(false); + theFakeVimSetting(ConfigUseFakeVim)->setValue(false); } void FakeVimPluginPrivate::showCommandBuffer(const QString &contents) diff --git a/src/plugins/projectexplorer/applicationlauncher_x11.cpp b/src/plugins/projectexplorer/applicationlauncher_x11.cpp index b82db98a4168c205705c51759ed8025196d12827..b79c25ff82ccfa3b6a6d246d6b72ef5dbc251ca3 100644 --- a/src/plugins/projectexplorer/applicationlauncher_x11.cpp +++ b/src/plugins/projectexplorer/applicationlauncher_x11.cpp @@ -30,6 +30,8 @@ #include "applicationlauncher.h" #include "consoleprocess.h" +#include <coreplugin/icore.h> + #include <QtCore/QTimer> using namespace ProjectExplorer::Internal; @@ -52,6 +54,7 @@ ApplicationLauncher::ApplicationLauncher(QObject *parent) this, SLOT(bringToForeground())); m_consoleProcess = new ConsoleProcess(this); + m_consoleProcess->setSettings(Core::ICore::instance()->settings()); connect(m_consoleProcess, SIGNAL(processError(const QString&)), this, SIGNAL(applicationError(const QString&))); connect(m_consoleProcess, SIGNAL(processStopped()), diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 7106ac1383c494d194ccbb73f177121d3c012f5d..3f83f4763e75a922fe13c783c47ec6c0b9c6f854 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -453,6 +453,7 @@ void Project::addRunConfiguration(QSharedPointer<RunConfiguration> runConfigurat return; } m_runConfigurations.push_back(runConfiguration); + emit addedRunConfiguration(runConfiguration->name()); } void Project::removeRunConfiguration(QSharedPointer<RunConfiguration> runConfiguration) @@ -460,14 +461,19 @@ void Project::removeRunConfiguration(QSharedPointer<RunConfiguration> runConfigu if(!m_runConfigurations.contains(runConfiguration)) { qWarning()<<"Not removing runConfiguration"<<runConfiguration->name()<<"becasue it doesn't exist"; return; - } - m_runConfigurations.removeOne(runConfiguration); + } + if (m_activeRunConfiguration == runConfiguration) { - if (m_runConfigurations.isEmpty()) + if (m_runConfigurations.size() <= 1) setActiveRunConfiguration(QSharedPointer<RunConfiguration>(0)); + else if (m_runConfigurations.at(0) == m_activeRunConfiguration) + setActiveRunConfiguration(m_runConfigurations.at(1)); else setActiveRunConfiguration(m_runConfigurations.at(0)); } + + m_runConfigurations.removeOne(runConfiguration); + emit removedRunConfiguration(runConfiguration->name()); } QSharedPointer<RunConfiguration> Project::activeRunConfiguration() const diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index fc8b9960a6b764dc5e3b9f4f306beb514e7a1236..bfe5872e781a1e3747b246a181fcb81b27c01537 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -140,6 +140,8 @@ signals: void fileListChanged(); void activeBuildConfigurationChanged(); void activeRunConfigurationChanged(); + void removedRunConfiguration(const QString &name); + void addedRunConfiguration(const QString &name); // This signal is jut there for updating the tree list in the buildsettings wizard void buildConfigurationDisplayNameChanged(const QString &buildConfiguraiton); diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.cpp b/src/plugins/projectexplorer/runsettingspropertiespage.cpp index bf4c56463761dde0a16c6413bd3b6ac1e4455408..b8c427168724b9ea236e3780a964dfc35987e93d 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/runsettingspropertiespage.cpp @@ -189,6 +189,15 @@ RunSettingsWidget::RunSettingsWidget(Project *project) connect(m_ui->removeToolButton, SIGNAL(clicked(bool)), this, SLOT(removeRunConfiguration())); + connect(m_project, SIGNAL(removedRunConfiguration(QString)), + this, SLOT(initRunConfigurationComboBox())); + + connect(m_project, SIGNAL(addedRunConfiguration(QString)), + this, SLOT(initRunConfigurationComboBox())); + + connect(m_project, SIGNAL(activeRunConfigurationChanged()), + this, SLOT(activeRunConfigurationChanged())); + initRunConfigurationComboBox(); const QList<QSharedPointer<RunConfiguration> > runConfigurations = m_project->runConfigurations(); for (int i=0; i<runConfigurations.size(); ++i) { @@ -285,6 +294,14 @@ void RunSettingsWidget::activateRunConfiguration(int index) m_ui->groupBox->layout()->addWidget(m_runConfigurationWidget); } +void RunSettingsWidget::activeRunConfigurationChanged() +{ + QSharedPointer<RunConfiguration> active = m_project->activeRunConfiguration(); + delete m_runConfigurationWidget; + m_runConfigurationWidget = active->configurationWidget(); + m_ui->groupBox->layout()->addWidget(m_runConfigurationWidget); +} + void RunSettingsWidget::nameChanged() { RunConfiguration *rc = qobject_cast<RunConfiguration *>(sender()); diff --git a/src/plugins/projectexplorer/runsettingspropertiespage.h b/src/plugins/projectexplorer/runsettingspropertiespage.h index 9caab4e4ac21d7c18e9f1b121b743fda0130fc48..1412ad712719a5602617775655faaa6184c5fa1d 100644 --- a/src/plugins/projectexplorer/runsettingspropertiespage.h +++ b/src/plugins/projectexplorer/runsettingspropertiespage.h @@ -77,9 +77,9 @@ private slots: void addRunConfiguration(); void removeRunConfiguration(); void nameChanged(); - -private: void initRunConfigurationComboBox(); + void activeRunConfigurationChanged(); +private: Project *m_project; RunConfigurationsModel *m_runConfigurationsModel; Ui::RunSettingsPropertiesPage *m_ui; diff --git a/src/plugins/qt4projectmanager/showbuildlog.ui b/src/plugins/qt4projectmanager/showbuildlog.ui index 98c61b360e7d1b59c27b4bdc748d742365c5bee0..5b31a76861cae86015ba20b776c6d28ebabebce4 100644 --- a/src/plugins/qt4projectmanager/showbuildlog.ui +++ b/src/plugins/qt4projectmanager/showbuildlog.ui @@ -11,7 +11,7 @@ </rect> </property> <property name="windowTitle"> - <string>Dialog</string> + <string>Debugging Helper Build Log</string> </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> diff --git a/src/plugins/texteditor/basetextdocument.cpp b/src/plugins/texteditor/basetextdocument.cpp old mode 100644 new mode 100755 index 07f0ce46260cc94124d9101241d32e6c661eae30..665dd5617aa72dcc61c2c067545eae7ce6f3947c --- a/src/plugins/texteditor/basetextdocument.cpp +++ b/src/plugins/texteditor/basetextdocument.cpp @@ -47,6 +47,12 @@ using namespace TextEditor; +#if defined (Q_OS_WIN) +QT_BEGIN_NAMESPACE +extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; +QT_END_NAMESPACE +#endif + #if defined (Q_OS_WIN) # define NATIVE_LINE_TERMINATOR CRLFLineTerminator #else @@ -140,8 +146,20 @@ bool BaseTextDocument::isReadOnly() const return true; if (m_fileName.isEmpty()) //have no corresponding file, so editing is ok return false; + const QFileInfo fi(m_fileName); - return !fi.isWritable(); + +#ifdef Q_OS_WIN + // Check for permissions on NTFS file systems + qt_ntfs_permission_lookup++; +#endif + + const bool ro = !fi.isWritable(); + +#ifdef Q_OS_WIN + qt_ntfs_permission_lookup--; +#endif + return ro; } bool BaseTextDocument::isModified() const @@ -157,19 +175,9 @@ bool BaseTextDocument::open(const QString &fileName) m_fileName = fi.absoluteFilePath(); QFile file(fileName); - if (!file.exists()) - return false; - - if (!fi.isReadable()) + if (!file.open(QIODevice::ReadOnly)) return false; - if (!fi.isWritable()) { - if (!file.open(QIODevice::ReadOnly)) - return false; - } else { - if (!file.open(QIODevice::ReadWrite)) - return false; - } title = fi.fileName(); QByteArray buf = file.readAll(); diff --git a/src/shared/help/helpviewer.cpp b/src/shared/help/helpviewer.cpp index 5aaf78ee9af5a6ee2d86275e3e2ec47caa03dfb0..89a13358352a9f307b938d345fe792b253695e39 100644 --- a/src/shared/help/helpviewer.cpp +++ b/src/shared/help/helpviewer.cpp @@ -213,9 +213,8 @@ HelpViewer::HelpViewer(QHelpEngine *engine, CentralWidget *parent) : QWebView(parent), helpEngine(engine), parentWidget(parent) { setPage(new HelpPage(parent, helpEngine, this)); - // Enable JavaScript and Plugins for embedded videos - settings()->setAttribute(QWebSettings::PluginsEnabled, true); - settings()->setAttribute(QWebSettings::JavaEnabled, true); + settings()->setAttribute(QWebSettings::PluginsEnabled, false); + settings()->setAttribute(QWebSettings::JavaEnabled, false); page()->setNetworkAccessManager(new HelpNetworkAccessManager(engine, this)); diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index 19041d7bb77cb884663dfa89704630e98abb2d5e..1313f7c0306a6cf32f48d98fda9d309a5cc8c3d6 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -151,6 +151,8 @@ public: QString m_pendingComment; bool m_syntaxError; bool m_contNextLine; + bool m_inQuote; + int m_parens; /////////////// Evaluating pro file contents @@ -251,6 +253,8 @@ bool ProFileEvaluator::Private::read(ProFile *pro) // Parser state m_block = 0; m_commentItem = 0; + m_inQuote = false; + m_parens = 0; m_contNextLine = false; m_syntaxError = false; m_lineNo = 1; @@ -274,71 +278,83 @@ bool ProFileEvaluator::Private::parseLine(const QString &line0) if (m_blockstack.isEmpty()) return false; - ushort quote = 0; - int parens = 0; - bool contNextLine = false; + int parens = m_parens; + bool inQuote = m_inQuote; + bool escaped = false; QString line = line0.simplified(); for (int i = 0; !m_syntaxError && i < line.length(); ++i) { ushort c = line.at(i).unicode(); - if (quote && c == quote) - quote = 0; - else if (c == '(') - ++parens; - else if (c == ')') - --parens; - else if (c == '"' && (i == 0 || line.at(i - 1).unicode() != '\\')) - quote = c; - else if (!parens && !quote) { - if (c == '#') { - insertComment(line.mid(i + 1)); - contNextLine = m_contNextLine; - break; - } - if (c == '\\' && i >= line.count() - 1) { - updateItem(); - contNextLine = true; - continue; - } - if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) { - if (c == ' ') - updateItem(); - else - m_proitem += c; - continue; - } - if (c == ':') { - enterScope(false); - continue; - } - if (c == '{') { - enterScope(true); - continue; - } - if (c == '}') { - leaveScope(); + if (c == '#') { // Yep - no escaping possible + insertComment(line.mid(i + 1)); + escaped = m_contNextLine; + break; + } + if (!escaped) { + if (c == '\\') { + escaped = true; + m_proitem += c; continue; - } - if (c == '=') { - insertVariable(line, &i); + } else if (c == '"') { + inQuote = !inQuote; + m_proitem += c; continue; } - if (c == '|' || c == '!') { - insertOperator(c); - continue; + } else { + escaped = false; + } + if (!inQuote) { + if (c == '(') { + ++parens; + } else if (c == ')') { + --parens; + } else if (!parens) { + if (m_block && (m_block->blockKind() & ProBlock::VariableKind)) { + if (c == ' ') + updateItem(); + else + m_proitem += c; + continue; + } + if (c == ':') { + enterScope(false); + continue; + } + if (c == '{') { + enterScope(true); + continue; + } + if (c == '}') { + leaveScope(); + continue; + } + if (c == '=') { + insertVariable(line, &i); + continue; + } + if (c == '|' || c == '!') { + insertOperator(c); + continue; + } } } m_proitem += c; } - m_contNextLine = contNextLine; - - if (!m_syntaxError) { - updateItem(); - if (!m_contNextLine) - finalizeBlock(); + m_inQuote = inQuote; + m_parens = parens; + m_contNextLine = escaped; + if (escaped) { + m_proitem.chop(1); + return true; + } else { + if (!m_syntaxError) { + updateItem(); + if (!m_contNextLine) + finalizeBlock(); + } + return !m_syntaxError; } - return !m_syntaxError; } void ProFileEvaluator::Private::finalizeBlock() @@ -357,6 +373,9 @@ void ProFileEvaluator::Private::insertVariable(const QString &line, int *i) { ProVariable::VariableOperator opkind; + if (m_proitem.isEmpty()) // Line starting with '=', like a conflict marker + return; + switch (m_proitem.at(m_proitem.length() - 1).unicode()) { case '+': m_proitem.chop(1); @@ -636,11 +655,11 @@ bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) evaluateFile(mkspecDirectory + QLatin1String("/default/qmake.conf"), &ok); evaluateFile(mkspecDirectory + QLatin1String("/features/default_pre.prf"), &ok); - QStringList tmp = m_valuemap.value("CONFIG"); + QStringList tmp = m_valuemap.value(QLatin1String("CONFIG")); tmp.append(m_addUserConfigCmdArgs); foreach(const QString &remove, m_removeUserConfigCmdArgs) tmp.removeAll(remove); - m_valuemap.insert("CONFIG", tmp); + m_valuemap.insert(QLatin1String("CONFIG"), tmp); m_cumulative = cumulative; } @@ -2021,7 +2040,13 @@ ProFile *ProFileEvaluator::parsedProFile(const QString &fileName) { QFileInfo fi(fileName); if (fi.exists()) { - ProFile *pro = new ProFile(fi.absoluteFilePath()); + QString fn = QDir::cleanPath(fi.absoluteFilePath()); + foreach (const ProFile *pf, d->m_profileStack) + if (pf->fileName() == fn) { + errorMessage(d->format("circular inclusion of %1").arg(fn)); + return 0; + } + ProFile *pro = new ProFile(fn); if (d->read(pro)) return pro; delete pro; diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp index f59a54a6790c92e5b99ac94de0d93404559c0b92..13ece24e546c4eb56a9530658c3736f5cd4d88c6 100644 --- a/tests/auto/debugger/main.cpp +++ b/tests/auto/debugger/main.cpp @@ -142,6 +142,7 @@ int main(int argc, char *argv[]) if (args.size() == 2 && args.at(1) == "--run-debuggee") { runDebuggee(); + app.exec(); return 0; } diff --git a/tests/auto/fakevim/main.cpp b/tests/auto/fakevim/main.cpp index b82f1a13bcb22769b586e2848939fc846dfde9e6..a1ac3be78265bab1bb126840b88fa96b29401907 100644 --- a/tests/auto/fakevim/main.cpp +++ b/tests/auto/fakevim/main.cpp @@ -30,6 +30,8 @@ #include "fakevimhandler.h" #include <QtCore/QSet> + +#include <QtGui/QTextEdit> #include <QtGui/QPlainTextEdit> #include <QtTest/QtTest> @@ -37,13 +39,15 @@ using namespace FakeVim; using namespace FakeVim::Internal; +#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s) class tst_FakeVim : public QObject { Q_OBJECT public: - tst_FakeVim(); + tst_FakeVim(bool); + ~tst_FakeVim(); public slots: void changeStatusData(const QString &info) { m_statusData = info; } @@ -51,14 +55,17 @@ public slots: void changeExtraInformation(const QString &info) { m_infoMessage = info; } private slots: - void commandI(); void commandDollar(); void commandDown(); + void commandLeft(); + void commandRight(); + void commandI(); void commandUp(); + void commandW(); private: void setup(); - void send(const QString &command); // send a normal command + void send(const QString &command) { sendEx("normal " + command); } void sendEx(const QString &command); // send an ex command bool checkContentsHelper(QString expected, const char* file, int line); @@ -66,8 +73,9 @@ private: const char* file, int line); QString insertCursor(const QString &needle0); - QPlainTextEdit m_editor; - FakeVimHandler m_handler; + QTextEdit *m_textedit; + QPlainTextEdit *m_plaintextedit; + FakeVimHandler *m_handler; QList<QTextEdit::ExtraSelection> m_selection; QString m_statusMessage; @@ -79,6 +87,8 @@ private: }; const QString tst_FakeVim::lines = + /* 0 1 2 3 4 */ + /* 0123456789012345678901234567890123457890 */ "\n" "#include <QtCore>\n" "#include <QtGui>\n" @@ -92,46 +102,70 @@ const QString tst_FakeVim::lines = const QString tst_FakeVim::escape = QChar(27); -tst_FakeVim::tst_FakeVim() - : m_handler(&m_editor, this) +tst_FakeVim::tst_FakeVim(bool usePlainTextEdit) { - QObject::connect(&m_handler, SIGNAL(commandBufferChanged(QString)), - this, SLOT(changeStatusMessage(QString))); - QObject::connect(&m_handler, SIGNAL(extraInformationChanged(QString)), - this, SLOT(changeExtraInformation(QString))); - QObject::connect(&m_handler, SIGNAL(statusDataChanged(QString)), - this, SLOT(changeStatusData(QString))); + if (usePlainTextEdit) { + m_textedit = 0; + m_plaintextedit = new QPlainTextEdit; + } else { + m_textedit = new QTextEdit; + m_plaintextedit = 0; + } + m_handler = 0; +} + +tst_FakeVim::~tst_FakeVim() +{ + delete m_handler; + delete m_textedit; + delete m_plaintextedit; } void tst_FakeVim::setup() { + delete m_handler; + m_handler = 0; m_statusMessage.clear(); m_statusData.clear(); m_infoMessage.clear(); - m_editor.setPlainText(lines); - QTextCursor tc = m_editor.textCursor(); - tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); - m_editor.setTextCursor(tc); - m_editor.setPlainText(lines); - //m_editor.show(); - //qApp->exec(); - QCOMPARE(m_editor.toPlainText(), lines); -} + if (m_textedit) { + m_textedit->setPlainText(lines); + QTextCursor tc = m_textedit->textCursor(); + tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); + m_textedit->setTextCursor(tc); + m_textedit->setPlainText(lines); + m_handler = new FakeVimHandler(m_textedit); + } else { + m_plaintextedit->setPlainText(lines); + QTextCursor tc = m_plaintextedit->textCursor(); + tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor); + m_plaintextedit->setTextCursor(tc); + m_plaintextedit->setPlainText(lines); + m_handler = new FakeVimHandler(m_plaintextedit); + } -void tst_FakeVim::send(const QString &command) -{ - m_handler.handleCommand("normal " + command); + QObject::connect(m_handler, SIGNAL(commandBufferChanged(QString)), + this, SLOT(changeStatusMessage(QString))); + QObject::connect(m_handler, SIGNAL(extraInformationChanged(QString)), + this, SLOT(changeExtraInformation(QString))); + QObject::connect(m_handler, SIGNAL(statusDataChanged(QString)), + this, SLOT(changeStatusData(QString))); + + QCOMPARE(EDITOR(toPlainText()), lines); } void tst_FakeVim::sendEx(const QString &command) { - m_handler.handleCommand(command); + if (m_handler) + m_handler->handleCommand(command); + else + qDebug() << "NO HANDLER YET"; } bool tst_FakeVim::checkContentsHelper(QString want, const char* file, int line) { - QString got = m_editor.toPlainText(); - int pos = m_editor.textCursor().position(); + QString got = EDITOR(toPlainText()); + int pos = EDITOR(textCursor().position()); got = got.left(pos) + "@" + got.mid(pos); QStringList wantlist = want.split('\n'); QStringList gotlist = got.split('\n'); @@ -172,6 +206,10 @@ bool tst_FakeVim::checkHelper(bool ex, QString cmd, QString expected, do { if (!checkHelper(false, cmd, expected, __FILE__, __LINE__)) \ return; } while (0) +#define move(cmd, expected) \ + do { if (!checkHelper(false, cmd, insertCursor(expected), __FILE__, __LINE__)) \ + return; } while (0) + // Runs an ex command and checks the result. // Cursor position is marked by a '@' in the expected contents. #define checkEx(cmd, expected) \ @@ -183,14 +221,13 @@ QString tst_FakeVim::insertCursor(const QString &needle0) QString needle = needle0; needle.remove('@'); QString lines0 = lines; - lines0.replace(needle, needle0); - //qDebug() << "LINES: " << lines0; + int pos = lines0.indexOf(needle); + lines0.replace(pos, needle.size(), needle0); return lines0; } void tst_FakeVim::commandI() { - return; setup(); // empty insertion at start of document @@ -205,6 +242,8 @@ void tst_FakeVim::commandI() check("ixxx" + escape, "xx@x" + lines); check("u", "@" + lines); +return; + // combine insertions check("ia" + escape, "@a" + lines); check("ibx" + escape, "b@xa" + lines); @@ -219,28 +258,86 @@ void tst_FakeVim::commandI() void tst_FakeVim::commandDollar() { setup(); - check("j$", insertCursor("<QtCore>@")); - //check("j", insertCursor("<QtGui>@")); + move("j$", "<QtCore>@"); + move("j$", "<QtGui>@"); + move("2j", ")@"); } void tst_FakeVim::commandDown() { setup(); - check("j", insertCursor("@#include <QtCore")); - check("3j", insertCursor("@int main")); - check("4j", insertCursor("@ return app.exec()")); + move("j", "@#include <QtCore"); + move("3j", "@int main"); + move("4j", "@ return app.exec()"); } void tst_FakeVim::commandUp() { setup(); - check("j", insertCursor("@#include <QtCore")); - check("3j", insertCursor("@int main")); - check("4j", insertCursor("@ return app.exec()")); + 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(); + move("4j", "@int main"); + move("h", "@int main"); // no move over left border + move("$", "argv[])@"); + move("h", "argv[]@)"); + move("3h", "arg@v[])"); + move("50h", "@int main"); +} + +void tst_FakeVim::commandW() +{ + setup(); + move("w", "@#include <QtCore"); + move("w", "#@include <QtCore"); + move("w", "#include @<QtCore"); + move("3w", "@#include <QtGui"); } +/* +#include <QtCore> +#include <QtGui> + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + return app.exec(); +} +*/ + +int main(int argc, char *argv[]) \ +{ + int res = 0; + QApplication app(argc, argv); \ + + // Test with QPlainTextEdit. + tst_FakeVim plaintextedit(true); + res += QTest::qExec(&plaintextedit, argc, argv); + +#if 0 + // Test with QTextEdit, too. + tst_FakeVim textedit(false); + res += QTest::qExec(&textedit, argc, argv); +#endif + + return res; +} -QTEST_MAIN(tst_FakeVim) #include "main.moc" diff --git a/tests/manual/gdbdebugger/simple/plugin.cpp b/tests/manual/gdbdebugger/simple/plugin.cpp index df4c6c00ac6b3032ecb2fee86f8fbd9f32e1a1ae..2942ab3c7da74510eca531fbaa5746dfc8d99855 100644 --- a/tests/manual/gdbdebugger/simple/plugin.cpp +++ b/tests/manual/gdbdebugger/simple/plugin.cpp @@ -30,6 +30,7 @@ #include <stdio.h> #include <qglobal.h> + extern "C" Q_DECL_EXPORT int pluginTest() { int s = 0;