Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline

This commit is contained in:
Daniel Molkentin
2009-01-15 16:55:49 +01:00
36 changed files with 603 additions and 88 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

BIN
doc/qtcreator-vcs-diff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
doc/qtcreator-vcs-log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
doc/qtcreator-vcs-pane.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -53,6 +53,7 @@
\o \l{Build Settings} \o \l{Build Settings}
\o \l{Qt Version Management} \o \l{Qt Version Management}
\o \l{Writing a Simple Program with Qt Creator} \o \l{Writing a Simple Program with Qt Creator}
\o \l{Qt Creator and Version Control Systems}
\o \l{Navigating Quickly Around Your Code with Locator} \o \l{Navigating Quickly Around Your Code with Locator}
\o \l{Debugging with Qt Creator} \o \l{Debugging with Qt Creator}
\o \l{Tips and Tricks} \o \l{Tips and Tricks}
@@ -237,10 +238,14 @@
\i \i
\row \row
\i Indenting \i Indenting Blocks
\i \i
\row \row
\i Commenting or Uncommenting \i Commenting or Uncommenting Blocks
\i
\row
\i Switch between Header and Source
\i \i
\endtable \endtable
@@ -265,6 +270,11 @@
*/ */
/*!
*/
/*! /*!
\contentspage index.html \contentspage index.html
@@ -758,6 +768,136 @@
*/ */
/*!
\contentspage index.html
\previouspage creator-navigation.html
\page creator-version-control.html
\nextpage creator-debugging.html
\title Qt Creator and Version Control Systems
\table
\caption Version control systems supported by Qt Creator
\row
\i \bold{git}
\i \l{http://git-scm.com/}
\row
\i \bold{Subversion}
\i \l{http://subversion.tigris.org/}
\row
\i \bold{Perforce}
\i \l{http://www.perforce.com}
\endtable
\section1 Setup
Qt Creator uses the version control system's command line clients to
access your repositories. To set it up, you must ensure that these command
line clients can be located via the \c{PATH} environment variable. You can
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 qtcreator-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 \gui{Pull}
\i Pull changes from the remote repository. If there are locally
modified files, you will be prompted to stash those changes.
\row
\i \gui{Branches...}
\i Displays the branch dialog showing the local branches at the
top and remote branches at the bottom. To switch to the local
branch, simply double-click on it. Double-clicking on a remote
branch will first create a local branch with the same name that
tracks the remote branch, and then switch to it.
\image qtcreator-vcs-gitbranch.png
\endtable
*/
/*! /*!
\contentspage index.html \contentspage index.html

View File

@@ -87,6 +87,7 @@ void CMakeProject::parseCMakeLists(const QDir &directory)
CMakeCbpParser cbpparser; CMakeCbpParser cbpparser;
qDebug()<<"Parsing file "<<cbpFile; qDebug()<<"Parsing file "<<cbpFile;
if (cbpparser.parseCbpFile(cbpFile)) { if (cbpparser.parseCbpFile(cbpFile)) {
m_projectName = cbpparser.projectName();
qDebug()<<"Building Tree"; qDebug()<<"Building Tree";
// TODO do a intelligent updating of the tree // TODO do a intelligent updating of the tree
buildTree(m_rootNode, cbpparser.fileList()); buildTree(m_rootNode, cbpparser.fileList());
@@ -200,8 +201,7 @@ ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode *
QString CMakeProject::name() const QString CMakeProject::name() const
{ {
// TODO return m_projectName;
return "";
} }
Core::IFile *CMakeProject::file() const Core::IFile *CMakeProject::file() const
@@ -469,6 +469,8 @@ void CMakeCbpParser::parseProject()
readNext(); readNext();
if (isEndElement()) { if (isEndElement()) {
return; return;
} else if (name() == "Option") {
parseOption();
} else if (name() == "Unit") { } else if (name() == "Unit") {
parseUnit(); parseUnit();
} else if (name() == "Build") { } else if (name() == "Build") {
@@ -537,6 +539,26 @@ void CMakeCbpParser::parseTargetOption()
} }
} }
QString CMakeCbpParser::projectName() const
{
return m_projectName;
}
void CMakeCbpParser::parseOption()
{
if (attributes().hasAttribute("title"))
m_projectName = attributes().value("title").toString();
while (!atEnd()) {
readNext();
if (isEndElement()) {
return;
} else if(isStartElement()) {
parseUnknownElement();
}
}
}
void CMakeCbpParser::parseMakeCommand() void CMakeCbpParser::parseMakeCommand()
{ {
while (!atEnd()) { while (!atEnd()) {

View File

@@ -118,6 +118,7 @@ private:
CMakeManager *m_manager; CMakeManager *m_manager;
QString m_fileName; QString m_fileName;
CMakeFile *m_file; CMakeFile *m_file;
QString m_projectName;
// TODO probably need a CMake specific node structure // TODO probably need a CMake specific node structure
CMakeProjectNode* m_rootNode; CMakeProjectNode* m_rootNode;
@@ -137,10 +138,12 @@ public:
QList<ProjectExplorer::FileNode *> fileList(); QList<ProjectExplorer::FileNode *> fileList();
QStringList includeFiles(); QStringList includeFiles();
QList<CMakeTarget> targets(); QList<CMakeTarget> targets();
QString projectName() const;
private: private:
void parseCodeBlocks_project_file(); void parseCodeBlocks_project_file();
void parseProject(); void parseProject();
void parseBuild(); void parseBuild();
void parseOption();
void parseTarget(); void parseTarget();
void parseTargetOption(); void parseTargetOption();
void parseMakeCommand(); void parseMakeCommand();
@@ -157,6 +160,7 @@ private:
CMakeTarget m_target; CMakeTarget m_target;
bool m_targetType; bool m_targetType;
QList<CMakeTarget> m_targets; QList<CMakeTarget> m_targets;
QString m_projectName;
}; };
class CMakeFile : public Core::IFile class CMakeFile : public Core::IFile

View File

@@ -30,6 +30,7 @@ HEADERS += attachexternaldialog.h \
imports.h \ imports.h \
moduleshandler.h \ moduleshandler.h \
moduleswindow.h \ moduleswindow.h \
outputcollector.h \
procinterrupt.h \ procinterrupt.h \
registerhandler.h \ registerhandler.h \
registerwindow.h \ registerwindow.h \
@@ -40,7 +41,7 @@ HEADERS += attachexternaldialog.h \
threadswindow.h \ threadswindow.h \
watchhandler.h \ watchhandler.h \
watchwindow.h watchwindow.h
SOURCES += attachexternaldialog.cpp \ SOURCES += attachexternaldialog.cpp \
attachremotedialog.cpp \ attachremotedialog.cpp \
breakhandler.cpp \ breakhandler.cpp \
@@ -54,9 +55,9 @@ SOURCES += attachexternaldialog.cpp \
disassemblerwindow.cpp \ disassemblerwindow.cpp \
gdbengine.cpp \ gdbengine.cpp \
gdbmi.cpp \ gdbmi.cpp \
gdbengine.h \
moduleshandler.cpp \ moduleshandler.cpp \
moduleswindow.cpp \ moduleswindow.cpp \
outputcollector.cpp \
procinterrupt.cpp \ procinterrupt.cpp \
registerhandler.cpp \ registerhandler.cpp \
registerwindow.cpp \ registerwindow.cpp \

View File

@@ -94,7 +94,7 @@ DebuggerSettings::DebuggerSettings()
m_skipKnownFrames = false; m_skipKnownFrames = false;
m_debugDumpers = false; m_debugDumpers = false;
m_useToolTips = false; m_useToolTips = false;
m_useToolTips = false; m_useTerminal = false;
m_useCustomDumpers = true; m_useCustomDumpers = true;
} }
@@ -590,9 +590,9 @@ void DebuggerManager::notifyInferiorPidChanged(int pid)
emit inferiorPidChanged(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() void DebuggerManager::shutdown()

View File

@@ -166,7 +166,7 @@ private:
virtual ThreadsHandler *threadsHandler() = 0; virtual ThreadsHandler *threadsHandler() = 0;
virtual WatchHandler *watchHandler() = 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 *useCustomDumpersAction() const = 0;
//virtual QAction *debugDumpersAction() const = 0; //virtual QAction *debugDumpersAction() const = 0;
virtual bool skipKnownFrames() const = 0; virtual bool skipKnownFrames() const = 0;
@@ -200,6 +200,7 @@ public:
bool m_debugDumpers; bool m_debugDumpers;
bool m_useFastStart; bool m_useFastStart;
bool m_useToolTips; bool m_useToolTips;
bool m_useTerminal;
QString m_scriptFile; QString m_scriptFile;
}; };
@@ -285,7 +286,7 @@ public slots:
private slots: private slots:
void showDebuggerOutput(const QString &prefix, const QString &msg); void showDebuggerOutput(const QString &prefix, const QString &msg);
void showDebuggerInput(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 reloadDisassembler();
void disassemblerDockToggled(bool on); void disassemblerDockToggled(bool on);
@@ -365,7 +366,7 @@ signals:
void setSessionValueRequested(const QString &name, const QVariant &value); void setSessionValueRequested(const QString &name, const QVariant &value);
void configValueRequested(const QString &name, QVariant *value); void configValueRequested(const QString &name, QVariant *value);
void setConfigValueRequested(const QString &name, const QVariant &value); void setConfigValueRequested(const QString &name, const QVariant &value);
void applicationOutputAvailable(const QString &prefix, const QString &msg); void applicationOutputAvailable(const QString &output);
public: public:
// FIXME: make private // FIXME: make private

View File

@@ -106,13 +106,7 @@ const char * const JUMP_TO_LINE = "Debugger.JumpToLine";
const char * const TOGGLE_BREAK = "Debugger.ToggleBreak"; const char * const TOGGLE_BREAK = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION = "Debugger.BreakByFunction"; const char * const BREAK_BY_FUNCTION = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN = "Debugger.BreakAtMain"; const char * const BREAK_AT_MAIN = "Debugger.BreakAtMain";
const char * const DEBUG_DUMPERS = "Debugger.DebugDumpers";
const char * const ADD_TO_WATCH = "Debugger.AddToWatch"; const char * const ADD_TO_WATCH = "Debugger.AddToWatch";
const char * const USE_CUSTOM_DUMPERS = "Debugger.UseCustomDumpers";
const char * const USE_FAST_START = "Debugger.UseFastStart";
const char * const USE_TOOL_TIPS = "Debugger.UseToolTips";
const char * const SKIP_KNOWN_FRAMES = "Debugger.SkipKnownFrames";
const char * const DUMP_LOG = "Debugger.DumpLog";
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
const char * const INTERRUPT_KEY = "Shift+F5"; const char * const INTERRUPT_KEY = "Shift+F5";
@@ -283,6 +277,7 @@ QWidget *GdbOptionPage::createPage(QWidget *parent)
m_ui.checkBoxUseCustomDumpers->setChecked(m_settings.m_useCustomDumpers); m_ui.checkBoxUseCustomDumpers->setChecked(m_settings.m_useCustomDumpers);
m_ui.checkBoxFastStart->setChecked(m_settings.m_useFastStart); m_ui.checkBoxFastStart->setChecked(m_settings.m_useFastStart);
m_ui.checkBoxUseToolTips->setChecked(m_settings.m_useToolTips); m_ui.checkBoxUseToolTips->setChecked(m_settings.m_useToolTips);
m_ui.checkBoxUseTerminal->setChecked(m_settings.m_useTerminal);
#ifndef QT_DEBUG #ifndef QT_DEBUG
#if 0 #if 0
@@ -291,10 +286,6 @@ QWidget *GdbOptionPage::createPage(QWidget *parent)
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L"))); //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11"))); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
mdebug->addAction(cmd); mdebug->addAction(cmd);
cmd = am->registerAction(m_manager->m_debugDumpersAction,
Constants::DEBUG_DUMPERS, debuggercontext);
mdebug->addAction(cmd);
#endif #endif
#endif #endif
@@ -325,6 +316,7 @@ void GdbOptionPage::apply()
m_settings.m_useCustomDumpers = m_ui.checkBoxUseCustomDumpers->isChecked(); m_settings.m_useCustomDumpers = m_ui.checkBoxUseCustomDumpers->isChecked();
m_settings.m_useFastStart = m_ui.checkBoxFastStart->isChecked(); m_settings.m_useFastStart = m_ui.checkBoxFastStart->isChecked();
m_settings.m_useToolTips = m_ui.checkBoxUseToolTips->isChecked(); m_settings.m_useToolTips = m_ui.checkBoxUseToolTips->isChecked();
m_settings.m_useTerminal = m_ui.checkBoxUseTerminal->isChecked();
*m_plugin->m_manager->settings() = m_settings; *m_plugin->m_manager->settings() = m_settings;
m_plugin->writeSettings(); m_plugin->writeSettings();
@@ -907,6 +899,7 @@ void DebuggerPlugin::writeSettings() const
s->setValue("UseFastStart", m->m_useFastStart); s->setValue("UseFastStart", m->m_useFastStart);
s->setValue("UseToolTips", m->m_useToolTips); s->setValue("UseToolTips", m->m_useToolTips);
s->setValue("UseTerminal", m->m_useTerminal);
s->setValue("UseCustomDumpers", m->m_useCustomDumpers); s->setValue("UseCustomDumpers", m->m_useCustomDumpers);
s->setValue("SkipKnowFrames", m->m_skipKnownFrames); s->setValue("SkipKnowFrames", m->m_skipKnownFrames);
s->setValue("DebugDumpers", m->m_debugDumpers); s->setValue("DebugDumpers", m->m_debugDumpers);
@@ -940,6 +933,7 @@ void DebuggerPlugin::readSettings()
m->m_useCustomDumpers = s->value("UseCustomDupers", false).toBool(); m->m_useCustomDumpers = s->value("UseCustomDupers", false).toBool();
m->m_useFastStart = s->value("UseFastStart", false).toBool(); m->m_useFastStart = s->value("UseFastStart", false).toBool();
m->m_useToolTips = s->value("UseToolTips", false).toBool(); m->m_useToolTips = s->value("UseToolTips", false).toBool();
m->m_useTerminal = s->value("UseTerminal", false).toBool();
s->endGroup(); s->endGroup();
m_manager->mainWindow()->restoreState(ba); m_manager->mainWindow()->restoreState(ba);

View File

@@ -108,8 +108,8 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager,
{ {
connect(m_manager, SIGNAL(debuggingFinished()), connect(m_manager, SIGNAL(debuggingFinished()),
this, SLOT(debuggingFinished())); this, SLOT(debuggingFinished()));
connect(m_manager, SIGNAL(applicationOutputAvailable(QString, QString)), connect(m_manager, SIGNAL(applicationOutputAvailable(QString)),
this, SLOT(slotAddToOutputWindow(QString, QString))); this, SLOT(slotAddToOutputWindowInline(QString)));
connect(m_manager, SIGNAL(inferiorPidChanged(qint64)), connect(m_manager, SIGNAL(inferiorPidChanged(qint64)),
this, SLOT(bringApplicationToForeground(qint64))); this, SLOT(bringApplicationToForeground(qint64)));
} }
@@ -138,12 +138,9 @@ void DebuggerRunControl::start()
debuggingFinished(); debuggingFinished();
} }
void DebuggerRunControl::slotAddToOutputWindow(const QString &prefix, const QString &line) void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data)
{ {
Q_UNUSED(prefix); emit addToOutputWindowInline(this, data);
foreach (const QString &l, line.split('\n'))
emit addToOutputWindow(this, prefix + Qt::escape(l));
//emit addToOutputWindow(this, prefix + Qt::escape(line));
} }
void DebuggerRunControl::stop() void DebuggerRunControl::stop()

View File

@@ -84,7 +84,7 @@ public:
private slots: private slots:
void debuggingFinished(); void debuggingFinished();
void slotAddToOutputWindow(const QString &prefix, const QString &line); void slotAddToOutputWindowInline(const QString &output);
private: private:
DebuggerManager *m_manager; DebuggerManager *m_manager;

View File

@@ -252,6 +252,7 @@ void GdbEngine::init()
m_pendingRequests = 0; m_pendingRequests = 0;
m_gdbVersion = 100; m_gdbVersion = 100;
m_shared = 0; m_shared = 0;
m_outputCodec = QTextCodec::codecForLocale();
m_oldestAcceptableToken = -1; m_oldestAcceptableToken = -1;
@@ -266,6 +267,8 @@ void GdbEngine::init()
SLOT(exitDebugger())); SLOT(exitDebugger()));
// Output // Output
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
SLOT(readDebugeeOutput(QByteArray)));
connect(this, SIGNAL(gdbResponseAvailable()), connect(this, SIGNAL(gdbResponseAvailable()),
this, SLOT(handleResponse()), Qt::QueuedConnection); this, SLOT(handleResponse()), Qt::QueuedConnection);
@@ -275,8 +278,8 @@ void GdbEngine::init()
connect(this, SIGNAL(gdbInputAvailable(QString,QString)), connect(this, SIGNAL(gdbInputAvailable(QString,QString)),
q, SLOT(showDebuggerInput(QString,QString)), q, SLOT(showDebuggerInput(QString,QString)),
Qt::QueuedConnection); Qt::QueuedConnection);
connect(this, SIGNAL(applicationOutputAvailable(QString,QString)), connect(this, SIGNAL(applicationOutputAvailable(QString)),
q, SLOT(showApplicationOutput(QString,QString)), q, SLOT(showApplicationOutput(QString)),
Qt::QueuedConnection); Qt::QueuedConnection);
} }
@@ -355,6 +358,12 @@ static void skipTerminator(const char *&from, const char *to)
skipSpaces(from, 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 // called asyncronously as response to Gdb stdout output in
// gdbResponseAvailable() // gdbResponseAvailable()
void GdbEngine::handleResponse() void GdbEngine::handleResponse()
@@ -407,22 +416,6 @@ void GdbEngine::handleResponse()
break; 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 // next char decides kind of record
const char c = *from++; const char c = *from++;
//qDebug() << "CODE:" << c; //qDebug() << "CODE:" << c;
@@ -590,8 +583,7 @@ static void fixMac(QByteArray &out)
void GdbEngine::readGdbStandardError() void GdbEngine::readGdbStandardError()
{ {
QByteArray err = m_gdbProc.readAllStandardError(); qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
emit applicationOutputAvailable("app-stderr:", err);
} }
void GdbEngine::readGdbStandardOutput() 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 // On Windows, the contents seem to depend on the debugger
// version and/or OS version used. // version and/or OS version used.
if (data.startsWith("warning:")) if (data.startsWith("warning:"))
qq->showApplicationOutput(QString(), data); qq->showApplicationOutput(data);
break; break;
} }
@@ -1484,6 +1476,7 @@ void GdbEngine::exitDebugger()
m_varToType.clear(); m_varToType.clear();
m_dataDumperState = DataDumperUninitialized; m_dataDumperState = DataDumperUninitialized;
m_shared = 0; m_shared = 0;
m_outputCollector.shutdown();
//q->settings()->m_debugDumpers = false; //q->settings()->m_debugDumpers = false;
} }
@@ -1506,6 +1499,15 @@ bool GdbEngine::startDebugger()
return false; 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("--quiet"));
gdbArgs.prepend(QLatin1String("mi")); gdbArgs.prepend(QLatin1String("mi"));
gdbArgs.prepend(QLatin1String("-i")); gdbArgs.prepend(QLatin1String("-i"));
@@ -1530,8 +1532,12 @@ bool GdbEngine::startDebugger()
m_gdbProc.start(q->settings()->m_gdbCmd, gdbArgs); m_gdbProc.start(q->settings()->m_gdbCmd, gdbArgs);
m_gdbProc.waitForStarted(); 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; return false;
}
q->showStatusMessage(tr("Gdb Running")); q->showStatusMessage(tr("Gdb Running"));

View File

@@ -36,6 +36,7 @@
#include "idebuggerengine.h" #include "idebuggerengine.h"
#include "gdbmi.h" #include "gdbmi.h"
#include "outputcollector.h"
#include <QtCore/QByteArray> #include <QtCore/QByteArray>
#include <QtCore/QHash> #include <QtCore/QHash>
@@ -43,6 +44,7 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QProcess> #include <QtCore/QProcess>
#include <QtCore/QPoint> #include <QtCore/QPoint>
#include <QtCore/QTextCodec>
#include <QtCore/QVariant> #include <QtCore/QVariant>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -93,7 +95,7 @@ signals:
void gdbResponseAvailable(); void gdbResponseAvailable();
void gdbInputAvailable(const QString &prefix, const QString &msg); void gdbInputAvailable(const QString &prefix, const QString &msg);
void gdbOutputAvailable(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: private:
// //
@@ -173,6 +175,7 @@ private slots:
void gdbProcError(QProcess::ProcessError error); void gdbProcError(QProcess::ProcessError error);
void readGdbStandardOutput(); void readGdbStandardOutput();
void readGdbStandardError(); void readGdbStandardError();
void readDebugeeOutput(const QByteArray &data);
private: private:
int terminationIndex(const QByteArray &buffer, int &length); int terminationIndex(const QByteArray &buffer, int &length);
@@ -190,6 +193,10 @@ private:
void handleQueryPwd(const GdbResultRecord &response); void handleQueryPwd(const GdbResultRecord &response);
void handleQuerySources(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response);
OutputCollector m_outputCollector;
QTextCodec *m_outputCodec;
QTextCodec::ConverterState m_outputCodecState;
QByteArray m_inbuffer; QByteArray m_inbuffer;
QProcess m_gdbProc; QProcess m_gdbProc;

View File

@@ -36,7 +36,7 @@
<widget class="QLineEdit" name="environmentEdit"/> <widget class="QLineEdit" name="environmentEdit"/>
</item> </item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="labelGdbLocaltion"> <widget class="QLabel" name="labelGdbLocation">
<property name="toolTip"> <property name="toolTip">
<string>This is either a full abolute path leading to the gdb binary you intend to use or the name of a gdb binary that wiull be searched in your PATH.</string> <string>This is either a full abolute path leading to the gdb binary you intend to use or the name of a gdb binary that wiull be searched in your PATH.</string>
</property> </property>
@@ -84,6 +84,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBoxUseTerminal">
<property name="toolTip">
<string>Start debugged process in a separte terminal.</string>
</property>
<property name="text">
<string>Start in terminal</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="checkBoxFastStart"> <widget class="QCheckBox" name="checkBoxFastStart">
<property name="toolTip"> <property name="toolTip">

View File

@@ -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

View File

@@ -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

View File

@@ -35,6 +35,13 @@
#include "fakevimconstants.h" #include "fakevimconstants.h"
// Please do not add any direct dependencies to other Qt Creator code here.
// Instead emit signals and let the FakeVimPlugin channel the information to
// Qt Creator. The idea is to keep this file here in a "clean" state that
// allows easy reuse with any QTextEdit or QPlainTextEdit derived class.
//#include <indenter.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QObject> #include <QtCore/QObject>
@@ -53,11 +60,6 @@
#include <QtGui/QTextDocumentFragment> #include <QtGui/QTextDocumentFragment>
#include <QtGui/QTextEdit> #include <QtGui/QTextEdit>
//#include <texteditor/basetexteditor.h>
//#include <texteditor/textblockiterator.h>
//#include <cppeditor/cppeditor.h>
//#include <indenter.h>
using namespace FakeVim::Internal; using namespace FakeVim::Internal;
using namespace FakeVim::Constants; using namespace FakeVim::Constants;
@@ -382,6 +384,9 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
return; return;
} }
if (m_visualMode != NoVisualMode)
m_marks['>'] = m_tc.position();
if (m_submode == ChangeSubMode) { if (m_submode == ChangeSubMode) {
if (!dotCommand.isEmpty()) if (!dotCommand.isEmpty())
m_dotCommand = "c" + dotCommand; m_dotCommand = "c" + dotCommand;
@@ -613,10 +618,8 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else if (key == ':') { } else if (key == ':') {
m_mode = ExMode; m_mode = ExMode;
m_commandBuffer.clear(); m_commandBuffer.clear();
if (m_visualMode != NoVisualMode) { if (m_visualMode != NoVisualMode)
m_commandBuffer = "'<,'>"; m_commandBuffer = "'<,'>";
leaveVisualMode();
}
m_commandHistory.append(QString()); m_commandHistory.append(QString());
m_commandHistoryIndex = m_commandHistory.size() - 1; m_commandHistoryIndex = m_commandHistory.size() - 1;
updateMiniBuffer(); updateMiniBuffer();
@@ -638,7 +641,6 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
m_submode = FilterSubMode; m_submode = FilterSubMode;
} else if (key == '!' && m_visualMode == VisualLineMode) { } else if (key == '!' && m_visualMode == VisualLineMode) {
m_mode = ExMode; m_mode = ExMode;
m_marks['>'] = m_tc.position();
m_commandBuffer = "'<,'>!"; m_commandBuffer = "'<,'>!";
m_commandHistory.append(QString()); m_commandHistory.append(QString());
m_commandHistoryIndex = m_commandHistory.size() - 1; m_commandHistoryIndex = m_commandHistory.size() - 1;
@@ -724,7 +726,7 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
} else if (key == 'G') { } else if (key == 'G') {
int n = m_mvcount.isEmpty() ? linesInDocument() : count(); int n = m_mvcount.isEmpty() ? linesInDocument() : count();
m_tc.setPosition(positionForLine(n), KeepAnchor); m_tc.setPosition(positionForLine(n), KeepAnchor);
if (m_config.contains(ConfigStartOfLine)) if (m_config[ConfigStartOfLine] == ConfigOn)
moveToFirstNonBlankOnLine(); moveToFirstNonBlankOnLine();
finishMovement(); finishMovement();
} else if (key == 'h' || key == Key_Left) { } else if (key == 'h' || key == Key_Left) {
@@ -1019,6 +1021,7 @@ bool FakeVimHandler::Private::handleMiniBufferModes(int key, const QString &text
m_commandHistory.takeLast(); m_commandHistory.takeLast();
m_commandHistory.append(m_commandBuffer); m_commandHistory.append(m_commandBuffer);
handleExCommand(m_commandBuffer); handleExCommand(m_commandBuffer);
leaveVisualMode();
} }
} else if (key == Key_Return && isSearchMode()) { } else if (key == Key_Return && isSearchMode()) {
if (!m_commandBuffer.isEmpty()) { if (!m_commandBuffer.isEmpty()) {
@@ -1138,7 +1141,6 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
if (cmd.startsWith("%")) if (cmd.startsWith("%"))
cmd = "1,$" + cmd.mid(1); cmd = "1,$" + cmd.mid(1);
m_marks['>'] = m_tc.position();
int beginLine = -1; int beginLine = -1;
int endLine = -1; int endLine = -1;
@@ -1192,10 +1194,9 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0)
showRedMessage(tr("File '%1' exists (add ! to override)").arg(fileName)); showRedMessage(tr("File '%1' exists (add ! to override)").arg(fileName));
} else if (file.open(QIODevice::ReadWrite)) { } else if (file.open(QIODevice::ReadWrite)) {
QTextCursor tc = selectRange(beginLine, endLine); QTextCursor tc = selectRange(beginLine, endLine);
qDebug() << "ANCHOR: " << tc.position() << tc.anchor() QString contents = tc.selection().toPlainText();
<< tc.selection().toPlainText(); emit q->writeFile(fileName, contents);
{ QTextStream ts(&file); ts << tc.selection().toPlainText(); } // check by reading back
file.close();
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QByteArray ba = file.readAll(); QByteArray ba = file.readAll();
showBlackMessage(tr("\"%1\" %2 %3L, %4C written") showBlackMessage(tr("\"%1\" %2 %3L, %4C written")
@@ -1813,3 +1814,8 @@ void FakeVimHandler::quit()
{ {
d->quit(); d->quit();
} }
void FakeVimHandler::setCurrentFileName(const QString &fileName)
{
d->m_currentFileName = fileName;
}

View File

@@ -58,6 +58,7 @@ public slots:
// FIXME: good idea? // FIXME: good idea?
void addWidget(QWidget *widget); void addWidget(QWidget *widget);
void removeWidget(QWidget *widget); void removeWidget(QWidget *widget);
void setCurrentFileName(const QString &fileName);
// This executes an "ex" style command taking context // This executes an "ex" style command taking context
// information from \p widget; // information from \p widget;
@@ -72,6 +73,7 @@ signals:
void quitRequested(QWidget *); void quitRequested(QWidget *);
void selectionChanged(QWidget *widget, void selectionChanged(QWidget *widget,
const QList<QTextEdit::ExtraSelection> &selection); const QList<QTextEdit::ExtraSelection> &selection);
void writeFile(const QString &fileName, const QString &contents);
private: private:
bool eventFilter(QObject *ob, QEvent *ev); bool eventFilter(QObject *ob, QEvent *ev);

View File

@@ -39,7 +39,9 @@
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/filemanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/ifile.h>
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <coreplugin/modemanager.h> #include <coreplugin/modemanager.h>
#include <coreplugin/uniqueidmanager.h> #include <coreplugin/uniqueidmanager.h>
@@ -117,12 +119,14 @@ private slots:
void editorAboutToClose(Core::IEditor *); void editorAboutToClose(Core::IEditor *);
void changeSelection(QWidget *widget, void changeSelection(QWidget *widget,
const QList<QTextEdit::ExtraSelection> &selections); const QList<QTextEdit::ExtraSelection> &selections);
void writeFile(const QString &fileName, const QString &contents);
private: private:
FakeVimPlugin *q; FakeVimPlugin *q;
FakeVimHandler *m_handler; FakeVimHandler *m_handler;
QAction *m_installHandlerAction; QAction *m_installHandlerAction;
Core::ICore *m_core; Core::ICore *m_core;
Core::IFile *m_currentFile;
}; };
} // namespace Internal } // namespace Internal
@@ -134,6 +138,7 @@ FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
m_handler = 0; m_handler = 0;
m_installHandlerAction = 0; m_installHandlerAction = 0;
m_core = 0; m_core = 0;
m_currentFile = 0;
} }
FakeVimPluginPrivate::~FakeVimPluginPrivate() FakeVimPluginPrivate::~FakeVimPluginPrivate()
@@ -206,6 +211,12 @@ void FakeVimPluginPrivate::installHandler(QWidget *widget)
this, SLOT(changeSelection(QWidget*,QList<QTextEdit::ExtraSelection>))); this, SLOT(changeSelection(QWidget*,QList<QTextEdit::ExtraSelection>)));
m_handler->addWidget(widget); 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); BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(widget);
if (bt) { 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) void FakeVimPluginPrivate::removeHandler(QWidget *widget)
{ {
Q_UNUSED(widget); Q_UNUSED(widget);
m_handler->removeWidget(widget); m_handler->removeWidget(widget);
Core::EditorManager::instance()->hideEditorInfoBar( Core::EditorManager::instance()->hideEditorInfoBar(
QLatin1String(Constants::MINI_BUFFER)); QLatin1String(Constants::MINI_BUFFER));
m_currentFile = 0;
} }
void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor) void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor)

View File

@@ -37,6 +37,9 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QProcess> #include <QtCore/QProcess>
#ifndef Q_OS_WIN
#include <QtCore/QTextCodec>
#endif
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
@@ -88,7 +91,12 @@ private:
ConsoleProcess *m_consoleProcess; ConsoleProcess *m_consoleProcess;
Mode m_currentMode; Mode m_currentMode;
#ifdef Q_OS_WIN
WinGuiProcess *m_winGuiProcess; WinGuiProcess *m_winGuiProcess;
#else
QTextCodec *m_outputCodec;
QTextCodec::ConverterState m_outputCodecState;
#endif
}; };
} // namespace Internal } // namespace Internal

View File

@@ -116,10 +116,7 @@ qint64 ApplicationLauncher::applicationPID() const
void ApplicationLauncher::readWinDebugOutput(const QString &output) void ApplicationLauncher::readWinDebugOutput(const QString &output)
{ {
QString s = output; emit appendOutput(output);
if (s.endsWith(QLatin1Char('\n')))
s.chop(1);
emit appendOutput(s);
} }
void ApplicationLauncher::processStopped() void ApplicationLauncher::processStopped()

View File

@@ -41,6 +41,7 @@ using namespace ProjectExplorer::Internal;
ApplicationLauncher::ApplicationLauncher(QObject *parent) ApplicationLauncher::ApplicationLauncher(QObject *parent)
: QObject(parent) : QObject(parent)
{ {
m_outputCodec = QTextCodec::codecForLocale();
m_currentMode = Gui; m_currentMode = Gui;
m_guiProcess = new QProcess(this); m_guiProcess = new QProcess(this);
m_guiProcess->setReadChannelMode(QProcess::MergedChannels); m_guiProcess->setReadChannelMode(QProcess::MergedChannels);
@@ -132,13 +133,9 @@ void ApplicationLauncher::guiProcessError()
void ApplicationLauncher::readStandardOutput() void ApplicationLauncher::readStandardOutput()
{ {
m_guiProcess->setReadChannel(QProcess::StandardOutput); QByteArray data = m_guiProcess->readAllStandardOutput();
while (m_guiProcess->canReadLine()) { emit appendOutput(m_outputCodec->toUnicode(
QString line = QString::fromLocal8Bit(m_guiProcess->readLine()); data.constData(), data.length(), &m_outputCodecState));
if (line.endsWith(QLatin1Char('\n')))
line.chop(1);
emit appendOutput(line);
}
} }
void ApplicationLauncher::processStopped() void ApplicationLauncher::processStopped()

View File

@@ -141,7 +141,7 @@ void ApplicationRunControl::start()
m_executable, rc->commandLineArguments()); m_executable, rc->commandLineArguments());
emit started(); emit started();
emit addToOutputWindow(this, tr("Starting %1").arg(m_executable)); emit addToOutputWindow(this, tr("Starting %1...").arg(m_executable));
} }
void ApplicationRunControl::stop() void ApplicationRunControl::stop()
@@ -162,7 +162,7 @@ void ApplicationRunControl::slotError(const QString & err)
void ApplicationRunControl::slotAddToOutputWindow(const QString &line) void ApplicationRunControl::slotAddToOutputWindow(const QString &line)
{ {
emit addToOutputWindow(this, Qt::escape(line)); emit addToOutputWindowInline(this, line);
} }
void ApplicationRunControl::processExited(int exitCode) void ApplicationRunControl::processExited(int exitCode)

View File

@@ -215,6 +215,12 @@ void OutputPane::appendOutput(RunControl *rc, const QString &out)
ow->appendOutput(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) void OutputPane::showTabFor(RunControl *rc)
{ {
OutputWindow *ow = m_outputWindows.value(rc); OutputWindow *ow = m_outputWindows.value(rc);
@@ -318,7 +324,16 @@ OutputWindow::~OutputWindow()
void OutputWindow::appendOutput(const QString &out) 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() void OutputWindow::insertLine()

View File

@@ -83,6 +83,7 @@ public:
// ApplicationOutputspecifics // ApplicationOutputspecifics
void createNewOutputWindow(RunControl *rc); void createNewOutputWindow(RunControl *rc);
void appendOutput(RunControl *rc, const QString &out); void appendOutput(RunControl *rc, const QString &out);
void appendOutputInline(RunControl *rc, const QString &out);
void showTabFor(RunControl *rc); void showTabFor(RunControl *rc);
public slots: public slots:
@@ -119,6 +120,7 @@ public:
~OutputWindow(); ~OutputWindow();
void appendOutput(const QString &out); void appendOutput(const QString &out);
void appendOutputInline(const QString &out);
void insertLine(); void insertLine();
}; };

View File

@@ -1084,6 +1084,8 @@ void ProjectExplorerPlugin::buildQueueFinished(bool success)
connect(control, SIGNAL(addToOutputWindow(RunControl *, const QString &)), connect(control, SIGNAL(addToOutputWindow(RunControl *, const QString &)),
this, SLOT(addToApplicationOutputWindow(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 &)), connect(control, SIGNAL(error(RunControl *, const QString &)),
this, SLOT(addErrorToApplicationOutputWindow(RunControl *, const QString &))); this, SLOT(addErrorToApplicationOutputWindow(RunControl *, const QString &)));
connect(control, SIGNAL(finished()), connect(control, SIGNAL(finished()),
@@ -1379,6 +1381,11 @@ void ProjectExplorerPlugin::addToApplicationOutputWindow(RunControl *rc, const Q
m_outputPane->appendOutput(rc, line); 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) void ProjectExplorerPlugin::addErrorToApplicationOutputWindow(RunControl *rc, const QString &error)
{ {
m_outputPane->appendOutput(rc, error); m_outputPane->appendOutput(rc, error);

View File

@@ -180,6 +180,7 @@ private slots:
void updateRunAction(); void updateRunAction();
void addToApplicationOutputWindow(RunControl *, const QString &line); void addToApplicationOutputWindow(RunControl *, const QString &line);
void addToApplicationOutputWindowInline(RunControl *, const QString &line);
void addErrorToApplicationOutputWindow(RunControl *, const QString &error); void addErrorToApplicationOutputWindow(RunControl *, const QString &error);
void updateTaskActions(); void updateTaskActions();

View File

@@ -143,6 +143,7 @@ public:
QSharedPointer<RunConfiguration> runConfiguration(); QSharedPointer<RunConfiguration> runConfiguration();
signals: signals:
void addToOutputWindow(RunControl *, const QString &line); void addToOutputWindow(RunControl *, const QString &line);
void addToOutputWindowInline(RunControl *, const QString &line);
void error(RunControl *, const QString &error); void error(RunControl *, const QString &error);
void started(); void started();
void finished(); void finished();

View File

@@ -730,9 +730,7 @@ namespace {
// updateSourceFiles() for files that changed // updateSourceFiles() for files that changed
// It does so by storing a modification time for each ui file we know about. // 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 // TODO this function should also be called if the build directory is changed
// since the build directory could change, and thus the generated files that are present
// TODO check that it works
void Qt4ProFileNode::updateUiFiles() void Qt4ProFileNode::updateUiFiles()
{ {
// Only those two project types can have ui files for us // Only those two project types can have ui files for us

View File

@@ -491,7 +491,7 @@ public:
class InfoItemModulesTest : public SPEInfoItem class InfoItemModulesTest : public SPEInfoItem
{ {
public: public:
InfoItemModulesTest(): SPEInfoItem("qtestlib", QtModule) InfoItemModulesTest(): SPEInfoItem("testlib", QtModule)
{ {
m_data.insert(keyIncludedByDefault, false); m_data.insert(keyIncludedByDefault, false);
} }

View File

@@ -39,6 +39,6 @@ extern "C" Q_DECL_EXPORT int pluginTest()
int s = 0; int s = 0;
for (int i = 1; i != 2000; ++i) for (int i = 1; i != 2000; ++i)
s += i; s += i;
fprintf(stderr, "in plugin test"); fprintf(stderr, "in plugin test\n");
return s; return s;
} }