diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 5a21d6a42d7a56248d4d2d0e1b21896f98a23985..469ea3460112218d7cec8eb0cfa7b2f5d836494b 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -30,6 +30,7 @@ HEADERS += attachexternaldialog.h \ imports.h \ moduleshandler.h \ moduleswindow.h \ + outputcollector.h \ procinterrupt.h \ registerhandler.h \ registerwindow.h \ @@ -40,7 +41,7 @@ HEADERS += attachexternaldialog.h \ threadswindow.h \ watchhandler.h \ watchwindow.h - + SOURCES += attachexternaldialog.cpp \ attachremotedialog.cpp \ breakhandler.cpp \ @@ -54,9 +55,9 @@ SOURCES += attachexternaldialog.cpp \ disassemblerwindow.cpp \ gdbengine.cpp \ gdbmi.cpp \ - gdbengine.h \ moduleshandler.cpp \ moduleswindow.cpp \ + outputcollector.cpp \ procinterrupt.cpp \ registerhandler.cpp \ registerwindow.cpp \ diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index ea0e6623b067aec04e98f8b272e476c426d3da36..e2840fb718058aab2710f7b57431ae1fa0ccc8cd 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -590,9 +590,9 @@ void DebuggerManager::notifyInferiorPidChanged(int pid) emit inferiorPidChanged(pid); } -void DebuggerManager::showApplicationOutput(const QString &prefix, const QString &str) +void DebuggerManager::showApplicationOutput(const QString &str) { - emit applicationOutputAvailable(prefix, str); + emit applicationOutputAvailable(str); } void DebuggerManager::shutdown() diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index 9a5b5da37d3e2e55dc7dcf7054e7755aeecd6f27..f3d76bb531eb4865331f5d369e7c4c5e6fc71cc6 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -166,7 +166,7 @@ private: virtual ThreadsHandler *threadsHandler() = 0; virtual WatchHandler *watchHandler() = 0; - virtual void showApplicationOutput(const QString &prefix, const QString &data) = 0; + virtual void showApplicationOutput(const QString &data) = 0; //virtual QAction *useCustomDumpersAction() const = 0; //virtual QAction *debugDumpersAction() const = 0; virtual bool skipKnownFrames() const = 0; @@ -285,7 +285,7 @@ public slots: private slots: void showDebuggerOutput(const QString &prefix, const QString &msg); void showDebuggerInput(const QString &prefix, const QString &msg); - void showApplicationOutput(const QString &prefix, const QString &msg); + void showApplicationOutput(const QString &data); void reloadDisassembler(); void disassemblerDockToggled(bool on); @@ -365,7 +365,7 @@ signals: void setSessionValueRequested(const QString &name, const QVariant &value); void configValueRequested(const QString &name, QVariant *value); void setConfigValueRequested(const QString &name, const QVariant &value); - void applicationOutputAvailable(const QString &prefix, const QString &msg); + void applicationOutputAvailable(const QString &output); public: // FIXME: make private diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 45eecd6514e5919d3142043353c5bb721143d5bb..7f3e42f47fa122af31fd00454dbd7ca595c141ee 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -108,8 +108,8 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, { connect(m_manager, SIGNAL(debuggingFinished()), this, SLOT(debuggingFinished())); - connect(m_manager, SIGNAL(applicationOutputAvailable(QString, QString)), - this, SLOT(slotAddToOutputWindow(QString, QString))); + connect(m_manager, SIGNAL(applicationOutputAvailable(QString)), + this, SLOT(slotAddToOutputWindowInline(QString))); connect(m_manager, SIGNAL(inferiorPidChanged(qint64)), this, SLOT(bringApplicationToForeground(qint64))); } @@ -138,12 +138,9 @@ void DebuggerRunControl::start() debuggingFinished(); } -void DebuggerRunControl::slotAddToOutputWindow(const QString &prefix, const QString &line) +void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) { - Q_UNUSED(prefix); - foreach (const QString &l, line.split('\n')) - emit addToOutputWindow(this, prefix + Qt::escape(l)); - //emit addToOutputWindow(this, prefix + Qt::escape(line)); + emit addToOutputWindowInline(this, data); } void DebuggerRunControl::stop() diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index c10a84e479513583acbc5c642f78edb7ff30f24e..0c6d979c0107f89e79ce196beb4511ac5e577abb 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -84,7 +84,7 @@ public: private slots: void debuggingFinished(); - void slotAddToOutputWindow(const QString &prefix, const QString &line); + void slotAddToOutputWindowInline(const QString &output); private: DebuggerManager *m_manager; diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 2370a55eed2ec637c359c595bfe95268495d3012..78d2522639b22d572a29c9c915516465bcddc200 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -252,6 +252,7 @@ void GdbEngine::init() m_pendingRequests = 0; m_gdbVersion = 100; m_shared = 0; + m_outputCodec = QTextCodec::codecForLocale(); m_oldestAcceptableToken = -1; @@ -266,6 +267,8 @@ void GdbEngine::init() SLOT(exitDebugger())); // Output + connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)), + SLOT(readDebugeeOutput(QByteArray))); connect(this, SIGNAL(gdbResponseAvailable()), this, SLOT(handleResponse()), Qt::QueuedConnection); @@ -275,8 +278,8 @@ void GdbEngine::init() connect(this, SIGNAL(gdbInputAvailable(QString,QString)), q, SLOT(showDebuggerInput(QString,QString)), Qt::QueuedConnection); - connect(this, SIGNAL(applicationOutputAvailable(QString,QString)), - q, SLOT(showApplicationOutput(QString,QString)), + connect(this, SIGNAL(applicationOutputAvailable(QString)), + q, SLOT(showApplicationOutput(QString)), Qt::QueuedConnection); } @@ -355,6 +358,12 @@ static void skipTerminator(const char *&from, const char *to) skipSpaces(from, to); } +void GdbEngine::readDebugeeOutput(const QByteArray &data) +{ + emit applicationOutputAvailable(m_outputCodec->toUnicode( + data.constData(), data.length(), &m_outputCodecState)); +} + // called asyncronously as response to Gdb stdout output in // gdbResponseAvailable() void GdbEngine::handleResponse() @@ -407,22 +416,6 @@ void GdbEngine::handleResponse() break; } - if (token == -1 && *from != '&' && *from != '~' && *from != '*') { - // FIXME: On Linux the application's std::out is merged in here. - // High risk of falsely interpreting this as MI output. - // We assume that we _always_ use tokens, so not finding a token - // is a positive indication for the presence of application output. - QString s; - while (from != to && *from != '\n') - s += *from++; - //qDebug() << "UNREQUESTED DATA " << s << " TAKEN AS APPLICATION OUTPUT"; - //s += '\n'; - - m_inbuffer = QByteArray(from, to - from); - emit applicationOutputAvailable("app-stdout: ", s); - continue; - } - // next char decides kind of record const char c = *from++; //qDebug() << "CODE:" << c; @@ -590,8 +583,7 @@ static void fixMac(QByteArray &out) void GdbEngine::readGdbStandardError() { - QByteArray err = m_gdbProc.readAllStandardError(); - emit applicationOutputAvailable("app-stderr:", err); + qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError(); } void GdbEngine::readGdbStandardOutput() @@ -1078,7 +1070,7 @@ void GdbEngine::handleStreamOutput(const QString &data, char code) // On Windows, the contents seem to depend on the debugger // version and/or OS version used. if (data.startsWith("warning:")) - qq->showApplicationOutput(QString(), data); + qq->showApplicationOutput(data); break; } @@ -1484,6 +1476,7 @@ void GdbEngine::exitDebugger() m_varToType.clear(); m_dataDumperState = DataDumperUninitialized; m_shared = 0; + m_outputCollector.shutdown(); //q->settings()->m_debugDumpers = false; } @@ -1506,6 +1499,15 @@ bool GdbEngine::startDebugger() return false; } + if (!m_outputCollector.listen()) { + QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), + tr("Cannot set up communication with child process: %1") + .arg(m_outputCollector.errorString())); + return false; + } + + gdbArgs.prepend(QLatin1String("--tty=") + m_outputCollector.serverName()); + //gdbArgs.prepend(QLatin1String("--quiet")); gdbArgs.prepend(QLatin1String("mi")); gdbArgs.prepend(QLatin1String("-i")); @@ -1530,8 +1532,12 @@ bool GdbEngine::startDebugger() m_gdbProc.start(q->settings()->m_gdbCmd, gdbArgs); m_gdbProc.waitForStarted(); - if (m_gdbProc.state() != QProcess::Running) + if (m_gdbProc.state() != QProcess::Running) { + QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"), + tr("Cannot start debugger: %1").arg(m_gdbProc.errorString())); + m_outputCollector.shutdown(); return false; + } q->showStatusMessage(tr("Gdb Running")); diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index e07e6a228c39950761b53c41542f7930d2b6e459..60493a53e582233c19efbd7cd42e3b95f82cf17b 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -36,6 +36,7 @@ #include "idebuggerengine.h" #include "gdbmi.h" +#include "outputcollector.h" #include <QtCore/QByteArray> #include <QtCore/QHash> @@ -43,6 +44,7 @@ #include <QtCore/QObject> #include <QtCore/QProcess> #include <QtCore/QPoint> +#include <QtCore/QTextCodec> #include <QtCore/QVariant> QT_BEGIN_NAMESPACE @@ -93,7 +95,7 @@ signals: void gdbResponseAvailable(); void gdbInputAvailable(const QString &prefix, const QString &msg); void gdbOutputAvailable(const QString &prefix, const QString &msg); - void applicationOutputAvailable(const QString &prefix, const QString &msg); + void applicationOutputAvailable(const QString &output); private: // @@ -173,6 +175,7 @@ private slots: void gdbProcError(QProcess::ProcessError error); void readGdbStandardOutput(); void readGdbStandardError(); + void readDebugeeOutput(const QByteArray &data); private: int terminationIndex(const QByteArray &buffer, int &length); @@ -190,6 +193,10 @@ private: void handleQueryPwd(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response); + OutputCollector m_outputCollector; + QTextCodec *m_outputCodec; + QTextCodec::ConverterState m_outputCodecState; + QByteArray m_inbuffer; QProcess m_gdbProc; diff --git a/src/plugins/debugger/outputcollector.cpp b/src/plugins/debugger/outputcollector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f091ca9208409a73817d9d9fe241c8e87f181c9f --- /dev/null +++ b/src/plugins/debugger/outputcollector.cpp @@ -0,0 +1,180 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#include "outputcollector.h" + +#ifdef Q_OS_WIN + +#include <QtNetwork/QLocalServer> +#include <QtNetwork/QLocalSocket> +#include <QtCore/QCoreApplication> + +#else + +#include <QtCore/QFile> +#include <QtCore/QSocketNotifier> +#include <QtCore/QTemporaryFile> +#include <QtCore/QVarLengthArray> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> + +#endif + +namespace Debugger { +namespace Internal { + +OutputCollector::OutputCollector(QObject *parent) + : QObject(parent) +{ +#ifdef Q_OS_WIN + m_server = 0; + m_socket = 0; +#endif +} + +OutputCollector::~OutputCollector() +{ + shutdown(); +} + +bool OutputCollector::listen() +{ +#ifdef Q_OS_WIN + if (m_server) + return m_server->isListening(); + m_server = new QLocalServer(this); + connect(m_server, SIGNAL(newConnection()), SLOT(newConnectionAvailable())); + return m_server->listen(QLatin1String("creator-") + QCoreApplication::applicationPid()); // XXX how to make that secure? +#else + if (!m_serverPath.isEmpty()) + return true; + QByteArray codedServerPath; + forever { + { + QTemporaryFile tf; + if (!tf.open()) { + m_errorString = tr("Cannot create temporary file: %2").arg(tf.errorString()); + m_serverPath.clear(); + return false; + } + m_serverPath = tf.fileName(); + } + // By now the temp file was deleted again + codedServerPath = QFile::encodeName(m_serverPath); + if (!::mkfifo(codedServerPath.constData(), 0600)) + break; + if (errno != EEXIST) { + m_errorString = tr("Cannot create FiFo %1: %2").arg(m_serverPath, strerror(errno)); + m_serverPath.clear(); + return false; + } + } + if ((m_serverFd = ::open(codedServerPath.constData(), O_RDONLY|O_NONBLOCK)) < 0) { + m_errorString = tr("Cannot open FiFo %1: %2").arg(m_serverPath, strerror(errno)); + m_serverPath.clear(); + return false; + } + m_serverNotifier = new QSocketNotifier(m_serverFd, QSocketNotifier::Read, this); + connect(m_serverNotifier, SIGNAL(activated(int)), SLOT(bytesAvailable())); + return true; +#endif +} + +void OutputCollector::shutdown() +{ +#ifdef Q_OS_WIN + delete m_server; // Deletes socket as well (QObject parent) + m_server = 0; + m_socket = 0; +#else + if (!m_serverPath.isEmpty()) { + ::close(m_serverFd); + ::unlink(QFile::encodeName(m_serverPath).constData()); + delete m_serverNotifier; + m_serverPath.clear(); + } +#endif +} + +QString OutputCollector::errorString() const +{ +#ifdef Q_OS_WIN + return m_socket ? m_socket->errorString() : m_server->errorString(); +#else + return m_errorString; +#endif +} + +QString OutputCollector::serverName() const +{ +#ifdef Q_OS_WIN + return m_server->fullServerName(); +#else + return m_serverPath; +#endif +} + +#ifdef Q_OS_WIN +void OutputCollector::newConnectionAvailable() +{ + if (m_socket) + return; + m_socket = m_server->nextPendingConnection(); + connect(m_socket, SIGNAL(bytesAvailable()), SLOT(bytesAvailable())); +} +#endif + +void OutputCollector::bytesAvailable() +{ +#ifdef Q_OS_WIN + emit byteDelivery(m_socket->readAll()); +#else + size_t nbytes = 0; + if (::ioctl(m_serverFd, FIONREAD, (char *) &nbytes) < 0) + return; + QVarLengthArray<char, 8192> buff(nbytes); + if (::read(m_serverFd, buff.data(), nbytes) != (int)nbytes) + return; + if (nbytes) // Skip EOF notifications + emit byteDelivery(QByteArray::fromRawData(buff.data(), nbytes)); +#endif +} + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/outputcollector.h b/src/plugins/debugger/outputcollector.h new file mode 100644 index 0000000000000000000000000000000000000000..b84a1b361001de100bedae5a1c6859139adaf4a2 --- /dev/null +++ b/src/plugins/debugger/outputcollector.h @@ -0,0 +1,91 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#ifndef OUTPUT_COLLECTOR_H +#define OUTPUT_COLLECTOR_H + +#include <QtCore/QByteArray> +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE +class QLocalServer; +class QLocalSocket; +class QSocketNotifier; +QT_END_NAMESPACE + +namespace Debugger { +namespace Internal { + +/////////////////////////////////////////////////////////////////////// +// +// OutputCollector +// +/////////////////////////////////////////////////////////////////////// + +class OutputCollector : public QObject +{ + Q_OBJECT + +public: + OutputCollector(QObject *parent = 0); + ~OutputCollector(); + bool listen(); + void shutdown(); + QString serverName() const; + QString errorString() const; + +signals: + void byteDelivery(const QByteArray &data); + +private slots: + void bytesAvailable(); +#ifdef Q_OS_WIN + void newConnectionAvailable(); +#endif + +private: +#ifdef Q_OS_WIN + QLocalServer *m_server; + QLocalSocket *m_socket; +#else + QString m_serverPath; + int m_serverFd; + QSocketNotifier *m_serverNotifier; + QString m_errorString; +#endif +}; + +} // namespace Internal +} // namespace Debugger + +#endif // OUTPUT_COLLECTOR_H diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp index a56fad81d510e603d9818a3d95362aa446b1426d..29f8c323d1fb0197d084849673c096f10fb9d1fd 100644 --- a/src/plugins/fakevim/fakevimhandler.cpp +++ b/src/plugins/fakevim/fakevimhandler.cpp @@ -40,10 +40,6 @@ // 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. -#include <coreplugin/filemanager.h> -#include <coreplugin/icore.h> -#include <texteditor/basetexteditor.h> - //#include <indenter.h> #include <QtCore/QDebug> @@ -226,7 +222,6 @@ public: bool m_wasReadOnly; // saves read-only state of document FakeVimHandler *q; - Core::ICore *m_core; Mode m_mode; SubMode m_submode; SubSubMode m_subsubmode; @@ -246,7 +241,6 @@ public: QString m_commandBuffer; QString m_currentFileName; - Core::IFile* m_currentFile; QString m_currentMessage; bool m_lastSearchForward; @@ -309,8 +303,6 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_visualMode = NoVisualMode; m_desiredColumn = 0; - m_core = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>(); - m_config[ConfigStartOfLine] = ConfigOn; m_config[ConfigTabStop] = "8"; m_config[ConfigSmartTab] = ConfigOff; @@ -734,7 +726,7 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'G') { int n = m_mvcount.isEmpty() ? linesInDocument() : count(); m_tc.setPosition(positionForLine(n), KeepAnchor); - if (m_config.contains(ConfigStartOfLine)) + if (m_config[ConfigStartOfLine] == ConfigOn) moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'h' || key == Key_Left) { @@ -1200,18 +1192,11 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0) bool exists = file.exists(); if (exists && !forced && !noArgs) { showRedMessage(tr("File '%1' exists (add ! to override)").arg(fileName)); - } else if (m_currentFile || file.open(QIODevice::ReadWrite)) { - if(m_currentFile) { - m_core->fileManager()->blockFileChange(m_currentFile); - m_currentFile->save(fileName); - m_core->fileManager()->unblockFileChange(m_currentFile); - } else { - QTextCursor tc = selectRange(beginLine, endLine); - qDebug() << "ANCHOR: " << tc.position() << tc.anchor() - << tc.selection().toPlainText(); - { QTextStream ts(&file); ts << tc.selection().toPlainText(); } - file.close(); - } + } else if (file.open(QIODevice::ReadWrite)) { + QTextCursor tc = selectRange(beginLine, endLine); + QString contents = tc.selection().toPlainText(); + emit q->writeFile(fileName, contents); + // check by reading back file.open(QIODevice::ReadOnly); QByteArray ba = file.readAll(); showBlackMessage(tr("\"%1\" %2 %3L, %4C written") @@ -1741,11 +1726,6 @@ void FakeVimHandler::Private::setWidget(QWidget *ob) { m_textedit = qobject_cast<QTextEdit *>(ob); m_plaintextedit = qobject_cast<QPlainTextEdit *>(ob); - TextEditor::BaseTextEditor* editor = qobject_cast<TextEditor::BaseTextEditor*>(ob); - if (editor) { - m_currentFile = editor->file(); - m_currentFileName = m_currentFile->fileName(); - } } /////////////////////////////////////////////////////////////////////// @@ -1834,3 +1814,8 @@ void FakeVimHandler::quit() { d->quit(); } + +void FakeVimHandler::setCurrentFileName(const QString &fileName) +{ + d->m_currentFileName = fileName; +} diff --git a/src/plugins/fakevim/fakevimhandler.h b/src/plugins/fakevim/fakevimhandler.h index 08df6d21b12a526f307b34346e3517cd2c662673..aeba5ace87005fbb9a88460335122ac8743aa722 100644 --- a/src/plugins/fakevim/fakevimhandler.h +++ b/src/plugins/fakevim/fakevimhandler.h @@ -58,6 +58,7 @@ public slots: // FIXME: good idea? void addWidget(QWidget *widget); void removeWidget(QWidget *widget); + void setCurrentFileName(const QString &fileName); // This executes an "ex" style command taking context // information from \p widget; @@ -72,6 +73,7 @@ signals: void quitRequested(QWidget *); void selectionChanged(QWidget *widget, const QList<QTextEdit::ExtraSelection> &selection); + void writeFile(const QString &fileName, const QString &contents); private: bool eventFilter(QObject *ob, QEvent *ev); diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 0a06fe7c112700e3fc54a8b108b10c25218d0c85..a27e988f4b4fd7fe81a5b4fa980446ad38ca3801 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -39,7 +39,9 @@ #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/filemanager.h> #include <coreplugin/icore.h> +#include <coreplugin/ifile.h> #include <coreplugin/messagemanager.h> #include <coreplugin/modemanager.h> #include <coreplugin/uniqueidmanager.h> @@ -117,12 +119,14 @@ private slots: void editorAboutToClose(Core::IEditor *); void changeSelection(QWidget *widget, const QList<QTextEdit::ExtraSelection> &selections); + void writeFile(const QString &fileName, const QString &contents); private: FakeVimPlugin *q; FakeVimHandler *m_handler; QAction *m_installHandlerAction; Core::ICore *m_core; + Core::IFile *m_currentFile; }; } // namespace Internal @@ -134,6 +138,7 @@ FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin) m_handler = 0; m_installHandlerAction = 0; m_core = 0; + m_currentFile = 0; } FakeVimPluginPrivate::~FakeVimPluginPrivate() @@ -206,6 +211,12 @@ void FakeVimPluginPrivate::installHandler(QWidget *widget) this, SLOT(changeSelection(QWidget*,QList<QTextEdit::ExtraSelection>))); m_handler->addWidget(widget); + TextEditor::BaseTextEditor* editor = + qobject_cast<TextEditor::BaseTextEditor*>(widget); + if (editor) { + m_currentFile = editor->file(); + m_handler->setCurrentFileName(editor->file()->fileName()); + } BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(widget); if (bt) { @@ -225,12 +236,29 @@ void FakeVimPluginPrivate::installHandler(QWidget *widget) } } +void FakeVimPluginPrivate::writeFile(const QString &fileName, + const QString &contents) +{ + if (m_currentFile && fileName == m_currentFile->fileName()) { + // Handle that as a special case for nicer interaction with core + m_core->fileManager()->blockFileChange(m_currentFile); + m_currentFile->save(fileName); + m_core->fileManager()->unblockFileChange(m_currentFile); + } else { + QFile file(fileName); + file.open(QIODevice::ReadWrite); + { QTextStream ts(&file); ts << contents; } + file.close(); + } +} + void FakeVimPluginPrivate::removeHandler(QWidget *widget) { Q_UNUSED(widget); m_handler->removeWidget(widget); Core::EditorManager::instance()->hideEditorInfoBar( QLatin1String(Constants::MINI_BUFFER)); + m_currentFile = 0; } void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor) diff --git a/src/plugins/projectexplorer/applicationlauncher.h b/src/plugins/projectexplorer/applicationlauncher.h index ead2799453e5722472b2508577c62fb1ed7869c3..82876e61f76b372da90ea9694331e3ee953069af 100644 --- a/src/plugins/projectexplorer/applicationlauncher.h +++ b/src/plugins/projectexplorer/applicationlauncher.h @@ -37,6 +37,9 @@ #include <QtCore/QObject> #include <QtCore/QStringList> #include <QtCore/QProcess> +#ifndef Q_OS_WIN +#include <QtCore/QTextCodec> +#endif namespace ProjectExplorer { namespace Internal { @@ -88,7 +91,12 @@ private: ConsoleProcess *m_consoleProcess; Mode m_currentMode; +#ifdef Q_OS_WIN WinGuiProcess *m_winGuiProcess; +#else + QTextCodec *m_outputCodec; + QTextCodec::ConverterState m_outputCodecState; +#endif }; } // namespace Internal diff --git a/src/plugins/projectexplorer/applicationlauncher_win.cpp b/src/plugins/projectexplorer/applicationlauncher_win.cpp index c6279b4c3cffd0b6da3508b1e44aa594b06808cd..374d26c97b15ea52280e047ba0d59070ea058710 100644 --- a/src/plugins/projectexplorer/applicationlauncher_win.cpp +++ b/src/plugins/projectexplorer/applicationlauncher_win.cpp @@ -116,10 +116,7 @@ qint64 ApplicationLauncher::applicationPID() const void ApplicationLauncher::readWinDebugOutput(const QString &output) { - QString s = output; - if (s.endsWith(QLatin1Char('\n'))) - s.chop(1); - emit appendOutput(s); + emit appendOutput(output); } void ApplicationLauncher::processStopped() diff --git a/src/plugins/projectexplorer/applicationlauncher_x11.cpp b/src/plugins/projectexplorer/applicationlauncher_x11.cpp index 79933d4518bddc89cf995ea2d33f1e8f3e86bb07..78214746a2ee8d0f7de68978a7c29b5c5a57cf6e 100644 --- a/src/plugins/projectexplorer/applicationlauncher_x11.cpp +++ b/src/plugins/projectexplorer/applicationlauncher_x11.cpp @@ -41,6 +41,7 @@ using namespace ProjectExplorer::Internal; ApplicationLauncher::ApplicationLauncher(QObject *parent) : QObject(parent) { + m_outputCodec = QTextCodec::codecForLocale(); m_currentMode = Gui; m_guiProcess = new QProcess(this); m_guiProcess->setReadChannelMode(QProcess::MergedChannels); @@ -132,13 +133,9 @@ void ApplicationLauncher::guiProcessError() void ApplicationLauncher::readStandardOutput() { - m_guiProcess->setReadChannel(QProcess::StandardOutput); - while (m_guiProcess->canReadLine()) { - QString line = QString::fromLocal8Bit(m_guiProcess->readLine()); - if (line.endsWith(QLatin1Char('\n'))) - line.chop(1); - emit appendOutput(line); - } + QByteArray data = m_guiProcess->readAllStandardOutput(); + emit appendOutput(m_outputCodec->toUnicode( + data.constData(), data.length(), &m_outputCodecState)); } void ApplicationLauncher::processStopped() diff --git a/src/plugins/projectexplorer/applicationrunconfiguration.cpp b/src/plugins/projectexplorer/applicationrunconfiguration.cpp index fc936d2c4311abe7911f03e6af8e20bc3baa42f2..0eeae6e8eef955d0a5dc30ee3710e03d847c6900 100644 --- a/src/plugins/projectexplorer/applicationrunconfiguration.cpp +++ b/src/plugins/projectexplorer/applicationrunconfiguration.cpp @@ -141,7 +141,7 @@ void ApplicationRunControl::start() m_executable, rc->commandLineArguments()); emit started(); - emit addToOutputWindow(this, tr("Starting %1").arg(m_executable)); + emit addToOutputWindow(this, tr("Starting %1...").arg(m_executable)); } void ApplicationRunControl::stop() @@ -162,7 +162,7 @@ void ApplicationRunControl::slotError(const QString & err) void ApplicationRunControl::slotAddToOutputWindow(const QString &line) { - emit addToOutputWindow(this, Qt::escape(line)); + emit addToOutputWindowInline(this, line); } void ApplicationRunControl::processExited(int exitCode) diff --git a/src/plugins/projectexplorer/outputwindow.cpp b/src/plugins/projectexplorer/outputwindow.cpp index c02f21ff34b32bc597edbf25fc8e3ae669e93ae3..d34c3f2bb0e3645d0928731c72c6b1587d3e5916 100644 --- a/src/plugins/projectexplorer/outputwindow.cpp +++ b/src/plugins/projectexplorer/outputwindow.cpp @@ -215,6 +215,12 @@ void OutputPane::appendOutput(RunControl *rc, const QString &out) ow->appendOutput(out); } +void OutputPane::appendOutputInline(RunControl *rc, const QString &out) +{ + OutputWindow *ow = m_outputWindows.value(rc); + ow->appendOutputInline(out); +} + void OutputPane::showTabFor(RunControl *rc) { OutputWindow *ow = m_outputWindows.value(rc); @@ -318,7 +324,16 @@ OutputWindow::~OutputWindow() void OutputWindow::appendOutput(const QString &out) { - appendPlainText(out); + if (out.endsWith('\n')) + appendPlainText(out); + else + appendPlainText(out + '\n'); +} + +void OutputWindow::appendOutputInline(const QString &out) +{ + moveCursor(QTextCursor::End); + insertPlainText(out); } void OutputWindow::insertLine() diff --git a/src/plugins/projectexplorer/outputwindow.h b/src/plugins/projectexplorer/outputwindow.h index 6bda6121af66f36e9b81ccc80ea60f1469f2ac8b..674f25cd51d728f41fd45b216e3faa73ee7e6fa4 100644 --- a/src/plugins/projectexplorer/outputwindow.h +++ b/src/plugins/projectexplorer/outputwindow.h @@ -83,6 +83,7 @@ public: // ApplicationOutputspecifics void createNewOutputWindow(RunControl *rc); void appendOutput(RunControl *rc, const QString &out); + void appendOutputInline(RunControl *rc, const QString &out); void showTabFor(RunControl *rc); public slots: @@ -119,6 +120,7 @@ public: ~OutputWindow(); void appendOutput(const QString &out); + void appendOutputInline(const QString &out); void insertLine(); }; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 2d6224bbdda90745ef71dee7fa8f90e7084f4f4a..c6cb624fb86bcc68d1bac08a803dc8049de768cd 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -1084,6 +1084,8 @@ void ProjectExplorerPlugin::buildQueueFinished(bool success) connect(control, SIGNAL(addToOutputWindow(RunControl *, const QString &)), this, SLOT(addToApplicationOutputWindow(RunControl *, const QString &))); + connect(control, SIGNAL(addToOutputWindowInline(RunControl *, const QString &)), + this, SLOT(addToApplicationOutputWindowInline(RunControl *, const QString &))); connect(control, SIGNAL(error(RunControl *, const QString &)), this, SLOT(addErrorToApplicationOutputWindow(RunControl *, const QString &))); connect(control, SIGNAL(finished()), @@ -1379,6 +1381,11 @@ void ProjectExplorerPlugin::addToApplicationOutputWindow(RunControl *rc, const Q m_outputPane->appendOutput(rc, line); } +void ProjectExplorerPlugin::addToApplicationOutputWindowInline(RunControl *rc, const QString &line) +{ + m_outputPane->appendOutputInline(rc, line); +} + void ProjectExplorerPlugin::addErrorToApplicationOutputWindow(RunControl *rc, const QString &error) { m_outputPane->appendOutput(rc, error); diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 2c1127ff5c63b06ef201db6f6a41d4359bace26e..1d270226d1ae1c370634be30a06fcd4720f698d3 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -180,6 +180,7 @@ private slots: void updateRunAction(); void addToApplicationOutputWindow(RunControl *, const QString &line); + void addToApplicationOutputWindowInline(RunControl *, const QString &line); void addErrorToApplicationOutputWindow(RunControl *, const QString &error); void updateTaskActions(); diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index acc11cd932ad0bdd68495d5287ddbc9968e8ea33..0bd593c20e24c40abd388252924694f234776908 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -143,6 +143,7 @@ public: QSharedPointer<RunConfiguration> runConfiguration(); signals: void addToOutputWindow(RunControl *, const QString &line); + void addToOutputWindowInline(RunControl *, const QString &line); void error(RunControl *, const QString &error); void started(); void finished(); diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 14fb56a38e951e040bc2e3bdc527a38e391605cb..c7bf1e5803503c0e085fcb8ffacc02cf47adf403 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -730,9 +730,7 @@ namespace { // updateSourceFiles() for files that changed // It does so by storing a modification time for each ui file we know about. -// TODO this function should also be called if the build configuration changes -// since the build directory could change, and thus the generated files that are present -// TODO check that it works +// TODO this function should also be called if the build directory is changed void Qt4ProFileNode::updateUiFiles() { // Only those two project types can have ui files for us diff --git a/src/plugins/qt4projectmanager/speinfo.cpp b/src/plugins/qt4projectmanager/speinfo.cpp index 04df918bb518e1a877a620382cddcadabf0c5196..16fa58741275bfbace74948515f5dd36e805df75 100644 --- a/src/plugins/qt4projectmanager/speinfo.cpp +++ b/src/plugins/qt4projectmanager/speinfo.cpp @@ -491,7 +491,7 @@ public: class InfoItemModulesTest : public SPEInfoItem { public: - InfoItemModulesTest(): SPEInfoItem("qtestlib", QtModule) + InfoItemModulesTest(): SPEInfoItem("testlib", QtModule) { m_data.insert(keyIncludedByDefault, false); } diff --git a/tests/manual/gdbdebugger/simple/plugin.cpp b/tests/manual/gdbdebugger/simple/plugin.cpp index 4e02c7f9f7e5628c7b000cfa93a41684dc0905d8..5e140d5811e85b65fbabd3307d2a2e0ada9aeade 100644 --- a/tests/manual/gdbdebugger/simple/plugin.cpp +++ b/tests/manual/gdbdebugger/simple/plugin.cpp @@ -39,6 +39,6 @@ extern "C" Q_DECL_EXPORT int pluginTest() int s = 0; for (int i = 1; i != 2000; ++i) s += i; - fprintf(stderr, "in plugin test"); + fprintf(stderr, "in plugin test\n"); return s; }