diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index 0d2fa7b6216dc25de8c8c1209a9f6c8acd0060f9..c8125fabd85a64056e83bb77b6a231d7d2662d69 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -797,9 +797,94 @@ specify the path to the command line client's executable in the settings pages that can be found under \gui{Options...} in the \gui{Tools} menu. - - + \section1 Usage + + You can find the version control menu entires in a sub-menu of the + \gui{Tools} menu. The version control system displayed here is the system + that manages the current project. + + Each version control system adds a pane to the \gui{Application Output} + panes within which it will log the commands it executes, prepended by a + timestamp and the relevant output. + + \image qtcreator-vcs-pane.png + + + \section2 Addings Files + + When you create a new file or a new project, the wizards will display page + requesting whether the files should be added to a version control system. + This depends on whether the parent directory or the project is already + under version control and the system supports the concept of adding files, + e.g., \bold{Perforce} and \bold{Subversion}. Alternatively, you can also + add files later on using the version control tool menus. + + With \bold{git}, there is no concept of adding files. Instead, all modified + files must be \e{staged} for a commit. + + + \section2 Viewing Diff Output + + All version control systems provide menu options to \e{diff} the current + file or project - comparing with the latest version stored in the + repository and displaying the differences. In Qt Creator, a diff is + displayed in a read-only editor. If the file is accessible, you can double + -click on a selected diff chunk and Qt Creator will open an editor + displaying the file, scrolled to the line in question. + + \image qtcreator-vcs-diff.png + + + \section2 Viewing Versioning History and Change Details + + The versioning history of a file can be displayed by selecting the + \gui{Log} (for \bold{git}) or \gui{Filelog (for \bold{Perforce} and + \bold{Subversion})} option. Typically, the log output will contain the + date, the commit message, and a change or revision identifier. If you + click on the identifier, a description of the change including the diff + will be displayed. + + \image qtcreator-vcs-log.png + \image qtcreaotr-vcs-describe.png + + + \section2 Annotating Files + + Annotation views are obtained by selecting \gui{Annotate} or \gui{Blame}. + This will display the lines of the file prepended by the change identifier + they originate from. Clicking on the change identifier shows a detailed + description of the file. + + + \section2 Committing Changes + + Once you have finished making changes, you can submit them to the version + control system by choosing \gui{Commit} or \gui{Submit}. Qt Creator will + display a commit page containing a text editor, where you can enter your + commit message, and a checkable list of modified files to be included. + When you are done, click \gui{Commit} to start committing. In addition, + there is a \gui{Diff selected} button that brings up a diff view of the + files selected in the file list. Since the commit page is just another + editor, you can go back to it by closing the diff view. Alternatively, you + can view it from the editor combo box showing the \gui{Opened files}. + + \image qtcreator-vcs-commit.png + + + \section2 Menu Entries Specific to git + + The git sub-menu contains additional entries: + + \table + \row + \i \gui{Stash} + \i Stash local changes prior to executing a \bold{pull}. + \row + \i + \i + \endtable + */ 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..9efb18c95a3c5ca4ff79628296be17e839d93e01 --- /dev/null +++ b/src/plugins/debugger/outputcollector.cpp @@ -0,0 +1,179 @@ +/*************************************************************************** +** +** 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> + +#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->fullServerPath(); +#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/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/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; }