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

This commit is contained in:
ck
2009-09-09 17:27:59 +02:00
35 changed files with 2551 additions and 1860 deletions

View File

@@ -500,7 +500,7 @@ void CMakeProject::setUserEnvironmentChanges(const QString &buildConfig, const Q
QStringList list = EnvironmentItem::toStringList(diff);
if (list == value(buildConfig, "userEnvironmentChanges"))
return;
setValue(buildConfig, "userEnvironmentChanges", EnvironmentItem::toStringList(diff));
setValue(buildConfig, "userEnvironmentChanges", list);
emit environmentChanged(buildConfig);
}

View File

@@ -527,8 +527,6 @@ CPPEditorEditable::CPPEditorEditable(CPPEditor *editor)
CPPEditor::CPPEditor(QWidget *parent)
: TextEditor::BaseTextEditor(parent)
, m_mouseNavigationEnabled(true)
, m_showingLink(false)
, m_currentRenameSelection(-1)
, m_inRename(false)
{
@@ -1073,7 +1071,7 @@ void CPPEditor::switchDeclarationDefinition()
}
CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
bool lookupDefinition)
bool resolveTarget)
{
Link link;
@@ -1153,7 +1151,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
if (Symbol *symbol = result.second) {
Symbol *def = 0;
if (lookupDefinition && !lastSymbol->isFunction())
if (resolveTarget && !lastSymbol->isFunction())
def = findDefinition(symbol);
link = linkToSymbol(def ? def : symbol);
@@ -1190,7 +1188,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
void CPPEditor::jumpToDefinition()
{
openCppEditorAt(findLinkAt(textCursor()));
openLink(findLinkAt(textCursor()));
}
Symbol *CPPEditor::findDefinition(Symbol *symbol)
@@ -1342,68 +1340,6 @@ void CPPEditor::contextMenuEvent(QContextMenuEvent *e)
delete menu;
}
void CPPEditor::mouseMoveEvent(QMouseEvent *e)
{
bool linkFound = false;
if (m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier) {
// Link emulation behaviour for 'go to definition'
const QTextCursor cursor = cursorForPosition(e->pos());
// Check that the mouse was actually on the text somewhere
bool onText = cursorRect(cursor).right() >= e->x();
if (!onText) {
QTextCursor nextPos = cursor;
nextPos.movePosition(QTextCursor::Right);
onText = cursorRect(nextPos).right() >= e->x();
}
const Link link = findLinkAt(cursor, false);
if (onText && !link.fileName.isEmpty()) {
showLink(link);
linkFound = true;
}
}
if (!linkFound)
clearLink();
TextEditor::BaseTextEditor::mouseMoveEvent(e);
}
void CPPEditor::mouseReleaseEvent(QMouseEvent *e)
{
if (m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier
&& !(e->modifiers() & Qt::ShiftModifier)
&& e->button() == Qt::LeftButton) {
const QTextCursor cursor = cursorForPosition(e->pos());
if (openCppEditorAt(findLinkAt(cursor))) {
clearLink();
e->accept();
return;
}
}
TextEditor::BaseTextEditor::mouseReleaseEvent(e);
}
void CPPEditor::leaveEvent(QEvent *e)
{
clearLink();
TextEditor::BaseTextEditor::leaveEvent(e);
}
void CPPEditor::keyReleaseEvent(QKeyEvent *e)
{
// Clear link emulation when Ctrl is released
if (e->key() == Qt::Key_Control)
clearLink();
TextEditor::BaseTextEditor::keyReleaseEvent(e);
}
void CPPEditor::keyPressEvent(QKeyEvent *e)
{
if (m_currentRenameSelection == -1) {
@@ -1491,29 +1427,6 @@ void CPPEditor::keyPressEvent(QKeyEvent *e)
TextEditor::BaseTextEditor::keyPressEvent(e);
}
void CPPEditor::showLink(const Link &link)
{
QTextEdit::ExtraSelection sel;
sel.cursor = textCursor();
sel.cursor.setPosition(link.pos);
sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor);
sel.format = m_linkFormat;
sel.format.setFontUnderline(true);
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel);
viewport()->setCursor(Qt::PointingHandCursor);
m_showingLink = true;
}
void CPPEditor::clearLink()
{
if (!m_showingLink)
return;
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
viewport()->setCursor(Qt::IBeamCursor);
m_showingLink = false;
}
QList<int> CPPEditorEditable::context() const
{
return m_context;
@@ -1557,17 +1470,10 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
highlighter->setFormats(formats.constBegin(), formats.constEnd());
highlighter->rehighlight();
m_linkFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_LINK));
m_occurrencesFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES));
m_occurrenceRenameFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES_RENAME));
}
void CPPEditor::setDisplaySettings(const TextEditor::DisplaySettings &ds)
{
TextEditor::BaseTextEditor::setDisplaySettings(ds);
m_mouseNavigationEnabled = ds.m_mouseNavigation;
}
void CPPEditor::unCommentSelection()
{
Core::Utils::unCommentSelection(this);

View File

@@ -193,7 +193,6 @@ public:
public Q_SLOTS:
virtual void setFontSettings(const TextEditor::FontSettings &);
virtual void setDisplaySettings(const TextEditor::DisplaySettings &);
void setSortedMethodOverview(bool sort);
void switchDeclarationDefinition();
void jumpToDefinition();
@@ -208,10 +207,6 @@ public Q_SLOTS:
protected:
bool event(QEvent *e);
void contextMenuEvent(QContextMenuEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void leaveEvent(QEvent *);
void keyReleaseEvent(QKeyEvent *);
void keyPressEvent(QKeyEvent *);
TextEditor::BaseTextEditorEditable *createEditableInterface();
@@ -261,36 +256,11 @@ private:
const QString &text = QString());
void abortRename();
struct Link
{
Link(const QString &fileName = QString(),
int line = 0,
int column = 0)
: pos(-1)
, length(-1)
, fileName(fileName)
, line(line)
, column(column)
{}
int pos; // Link position
int length; // Link length
QString fileName; // Target file
int line; // Target line
int column; // Target column
};
void showLink(const Link &);
void clearLink();
Link findLinkAt(const QTextCursor &, bool lookupDefinition = true);
static Link linkToSymbol(CPlusPlus::Symbol *symbol);
Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
bool openLink(const Link &link) { return openCppEditorAt(link); }
bool openCppEditorAt(const Link &);
bool m_mouseNavigationEnabled;
bool m_showingLink;
QTextCharFormat m_linkFormat;
static Link linkToSymbol(CPlusPlus::Symbol *symbol);
CppTools::CppModelManagerInterface *m_modelManager;

View File

@@ -73,6 +73,8 @@ void CppHighlighter::highlightBlock(const QString &text)
userData->setCollapseMode(TextBlockUserData::NoCollapse);
}
TextEditDocumentLayout::clearParentheses(currentBlock());
if (text.length()) // the empty line can still contain whitespace
setFormat(0, text.length(), visualSpaceFormat);
return;
}
@@ -171,7 +173,7 @@ void CppHighlighter::highlightBlock(const QString &text)
}
// mark the trailing white spaces
if (! tokens.isEmpty()) {
{
const SimpleToken tk = tokens.last();
const int lastTokenEnd = tk.position() + tk.length();
if (text.length() > lastTokenEnd)

View File

@@ -87,5 +87,7 @@ include(cdb/cdb.pri)
include(gdb/gdb.pri)
include(script/script.pri)
include(tcf/tcf.pri)
include(symbian/symbian.pri)
include(shared/shared.pri)
OTHER_FILES += Debugger.pluginspec

View File

@@ -103,6 +103,8 @@ namespace Internal {
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createSymbianEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
{
QDebug nospace = str.nospace();

View File

@@ -144,7 +144,7 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record)
//
///////////////////////////////////////////////////////////////////////
GdbEngine::GdbEngine(DebuggerManager *parent) :
GdbEngine::GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc) :
#ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
m_dumperInjectionLoad(true),
#else
@@ -153,6 +153,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
q(parent),
qq(parent->engineInterface())
{
m_gdbProc = gdbProc;
m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
#ifdef Q_OS_UNIX
m_stubProc.setSettings(Core::ICore::instance()->settings());
@@ -164,19 +165,20 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
GdbEngine::~GdbEngine()
{
// prevent sending error messages afterwards
m_gdbProc.disconnect(this);
m_gdbProc->disconnect(this);
delete m_gdbProc;
}
void GdbEngine::initializeConnections()
{
// Gdb Process interaction
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(gdbProcError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
connect(m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SLOT(readGdbStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
connect(m_gdbProc, SIGNAL(readyReadStandardError()),
this, SLOT(readGdbStandardError()));
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
connect(m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
q, SLOT(exitDebugger()));
connect(&m_stubProc, SIGNAL(processError(QString)),
@@ -614,7 +616,7 @@ void GdbEngine::stubError(const QString &msg)
void GdbEngine::readGdbStandardError()
{
qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
qWarning() << "Unexpected gdb stderr:" << m_gdbProc->readAllStandardError();
}
void GdbEngine::readGdbStandardOutput()
@@ -622,7 +624,7 @@ void GdbEngine::readGdbStandardOutput()
int newstart = 0;
int scan = m_inbuffer.size();
m_inbuffer.append(m_gdbProc.readAllStandardOutput());
m_inbuffer.append(m_gdbProc->readAllStandardOutput());
while (newstart < m_inbuffer.size()) {
int start = newstart;
@@ -651,7 +653,7 @@ void GdbEngine::interruptInferior()
{
qq->notifyInferiorStopRequested();
if (m_gdbProc.state() == QProcess::NotRunning) {
if (m_gdbProc->state() == QProcess::NotRunning) {
debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"));
qq->notifyInferiorExited();
return;
@@ -698,7 +700,7 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
GdbCommandCallback callback, const char *callbackName,
const QVariant &cookie)
{
if (m_gdbProc.state() == QProcess::NotRunning) {
if (m_gdbProc->state() == QProcess::NotRunning) {
debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command);
return;
}
@@ -742,7 +744,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd)
if (cmd.flags & EmbedToken)
cmd.command = cmd.command.arg(currentToken());
m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
m_gdbProc->write(cmd.command.toLatin1() + "\r\n");
//emit gdbInputAvailable(QString(), " " + currentTime());
//emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command);
emit gdbInputAvailable(LogInput, cmd.command);
@@ -829,12 +831,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
void GdbEngine::executeDebuggerCommand(const QString &command)
{
if (m_gdbProc.state() == QProcess::NotRunning) {
if (m_gdbProc->state() == QProcess::NotRunning) {
debugMessage(_("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: ") + command);
return;
}
m_gdbProc.write(command.toLocal8Bit() + "\r\n");
m_gdbProc->write(command.toLocal8Bit() + "\r\n");
}
void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &)
@@ -1434,15 +1436,15 @@ void GdbEngine::detachDebugger()
void GdbEngine::exitDebugger()
{
debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc.state()));
if (m_gdbProc.state() == QProcess::Starting) {
debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc->state()));
if (m_gdbProc->state() == QProcess::Starting) {
debugMessage(_("WAITING FOR GDB STARTUP TO SHUTDOWN: %1")
.arg(m_gdbProc.state()));
m_gdbProc.waitForStarted();
.arg(m_gdbProc->state()));
m_gdbProc->waitForStarted();
}
if (m_gdbProc.state() == QProcess::Running) {
if (m_gdbProc->state() == QProcess::Running) {
debugMessage(_("WAITING FOR RUNNING GDB TO SHUTDOWN: %1")
.arg(m_gdbProc.state()));
.arg(m_gdbProc->state()));
if (q->status() != DebuggerInferiorStopped
&& q->status() != DebuggerProcessStartingUp) {
QTC_ASSERT(q->status() == DebuggerInferiorRunning,
@@ -1455,17 +1457,17 @@ void GdbEngine::exitDebugger()
postCommand(_("kill"));
postCommand(_("-gdb-exit"), CB(handleExit));
// 20s can easily happen when loading webkit debug information
if (!m_gdbProc.waitForFinished(20000)) {
if (!m_gdbProc->waitForFinished(20000)) {
debugMessage(_("FORCING TERMINATION: %1")
.arg(m_gdbProc.state()));
m_gdbProc.terminate();
m_gdbProc.waitForFinished(20000);
.arg(m_gdbProc->state()));
m_gdbProc->terminate();
m_gdbProc->waitForFinished(20000);
}
}
if (m_gdbProc.state() != QProcess::NotRunning) {
if (m_gdbProc->state() != QProcess::NotRunning) {
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
.arg(m_gdbProc.state()));
m_gdbProc.kill();
.arg(m_gdbProc->state()));
m_gdbProc->kill();
}
m_outputCollector.shutdown();
@@ -1487,9 +1489,9 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
QStringList gdbArgs;
if (m_gdbProc.state() != QProcess::NotRunning) {
debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc.state()));
m_gdbProc.kill();
if (m_gdbProc->state() != QProcess::NotRunning) {
debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state()));
m_gdbProc->kill();
return false;
}
@@ -1529,16 +1531,16 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
if (!sp->workingDir.isEmpty())
m_gdbProc.setWorkingDirectory(sp->workingDir);
m_gdbProc->setWorkingDirectory(sp->workingDir);
if (!sp->environment.isEmpty())
m_gdbProc.setEnvironment(sp->environment);
m_gdbProc->setEnvironment(sp->environment);
}
#if 0
qDebug() << "Command:" << q->settings()->m_gdbCmd;
qDebug() << "WorkingDirectory:" << m_gdbProc.workingDirectory();
qDebug() << "WorkingDirectory:" << m_gdbProc->workingDirectory();
qDebug() << "ScriptFile:" << q->settings()->m_scriptFile;
qDebug() << "Environment:" << m_gdbProc.environment();
qDebug() << "Environment:" << m_gdbProc->environment();
qDebug() << "Arguments:" << gdbArgs;
qDebug() << "BuildDir:" << sp->buildDir;
qDebug() << "ExeFile:" << sp->executable;
@@ -1546,10 +1548,10 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
QString loc = theDebuggerStringSetting(GdbLocation);
q->showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
m_gdbProc.start(loc, gdbArgs);
if (!m_gdbProc.waitForStarted()) {
m_gdbProc->start(loc, gdbArgs);
if (!m_gdbProc->waitForStarted()) {
QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
tr("Cannot start debugger: %1").arg(m_gdbProc.errorString()));
tr("Cannot start debugger: %1").arg(m_gdbProc->errorString()));
m_outputCollector.shutdown();
m_stubProc.blockSignals(true);
m_stubProc.stop();
@@ -4198,7 +4200,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
{
opts->push_back(new GdbOptionsPage);
return new GdbEngine(parent);
return new GdbEngine(parent, new GdbProcess);
}
} // namespace Internal

View File

@@ -32,6 +32,7 @@
#include "idebuggerengine.h"
#include "gdbmi.h"
#include "gdbprocessbase.h"
#include "outputcollector.h"
#include "watchutils.h"
@@ -56,6 +57,7 @@ QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
class DebuggerManager;
class IDebuggerManagerAccessForEngines;
class GdbResultRecord;
@@ -72,13 +74,46 @@ enum DebuggingHelperState
DebuggingHelperUnavailable,
};
class GdbProcess : public GdbProcessBase
{
public:
GdbProcess(QObject *parent = 0)
: GdbProcessBase(parent)
{
connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
this, SIGNAL(error(QProcess::ProcessError)));
connect(&m_proc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_proc, SIGNAL(readyReadStandardError()),
this, SIGNAL(readyReadStandardError()));
connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SIGNAL(finished(int, QProcess::ExitStatus)));
}
void start(const QString &program, const QStringList &args,
QIODevice::OpenMode mode) { m_proc.start(program, args, mode); }
void kill() { m_proc.kill(); }
void terminate() { m_proc.terminate(); }
bool waitForStarted(int msecs) { return m_proc.waitForStarted(msecs); }
bool waitForFinished(int msecs) { return m_proc.waitForFinished(msecs); }
QProcess::ProcessState state() const { return m_proc.state(); }
QString errorString() const { return m_proc.errorString(); }
QByteArray readAllStandardError() { return m_proc.readAllStandardError(); }
QByteArray readAllStandardOutput() { return m_proc.readAllStandardOutput(); }
qint64 write(const char *data) { return m_proc.write(data); }
void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); }
void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); }
private:
QProcess m_proc;
};
class GdbEngine : public IDebuggerEngine
{
Q_OBJECT
public:
GdbEngine(DebuggerManager *parent);
GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc);
~GdbEngine();
signals:
@@ -251,7 +286,7 @@ private:
QByteArray m_inbuffer;
QProcess m_gdbProc;
GdbProcessBase *m_gdbProc;
QProcess m_uploadProc;
Core::Utils::ConsoleProcess m_stubProc;

View File

@@ -0,0 +1,74 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef DEBUGGER_PROCESSBASE_H
#define DEBUGGER_PROCESSBASE_H
#include <QtCore/QObject>
#include <QtCore/QProcess>
namespace Debugger {
namespace Internal {
// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter.
// In the GdbProcess case it's just a wrapper around a QProcess running
// gdb, in the Adapter case it's the interface to the gdb process in
// the whole rfomm/gdb/gdbserver combo.
class GdbProcessBase : public QObject
{
Q_OBJECT
public:
GdbProcessBase(QObject *parent = 0) : QObject(parent) {}
virtual void start(const QString &program, const QStringList &args,
QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0;
virtual void kill() = 0;
virtual void terminate() = 0;
virtual bool waitForStarted(int msecs = 30000) = 0;
virtual bool waitForFinished(int msecs = 30000) = 0;
virtual QProcess::ProcessState state() const = 0;
virtual QString errorString() const = 0;
virtual QByteArray readAllStandardError() = 0;
virtual QByteArray readAllStandardOutput() = 0;
virtual qint64 write(const char *data) = 0;
virtual void setWorkingDirectory(const QString &dir) = 0;
virtual void setEnvironment(const QStringList &env) = 0;
signals:
void error(QProcess::ProcessError);
void readyReadStandardOutput();
void readyReadStandardError();
void finished(int, QProcess::ExitStatus);
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_PROCESSBASE_H

View File

@@ -0,0 +1,14 @@
HEADERS += \
$$PWD/trkclient.h \
$$PWD/symbianadapter.h \
#$$PWD/gdboptionspage.h \
SOURCES += \
$$PWD/trkclient.cpp \
$$PWD/symbianadapter.cpp \
$$PWD/symbianengine.cpp \
#$$PWD/gdboptionspage.cpp \
#FORMS += $$PWD/gdboptionspage.ui
#RESOURCES += $$PWD/gdb.qrc

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,247 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef DEBUGGER_SYMBIANADAPTER_H
#define DEBUGGER_SYMBIANADAPTER_H
#include "trkutils.h"
#include "trkclient.h"
#include "../gdb/gdbprocessbase.h"
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QHash>
#include <QtCore/QPointer>
#include <QtCore/QProcess>
#include <QtCore/QQueue>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
#include <QtCore/QTimer>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>
#include <QtGui/QKeyEvent>
#include <QtGui/QTextBlock>
#include <QtGui/QTextEdit>
#include <QtGui/QToolBar>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
namespace Debugger {
namespace Internal {
struct GdbResult
{
QByteArray data;
};
///////////////////////////////////////////////////////////////////////
//
// SymbianAdapter
//
///////////////////////////////////////////////////////////////////////
class SymbianAdapter : public GdbProcessBase
{
Q_OBJECT
public:
typedef trk::TrkResult TrkResult;
typedef trk::TrkFunctor1<const TrkResult &> TrkCallback;
typedef trk::TrkFunctor1<const GdbResult &> GdbCallback;
SymbianAdapter();
~SymbianAdapter();
void setGdbServerName(const QString &name);
QString gdbServerIP() const;
uint gdbServerPort() const;
void setVerbose(int verbose) { m_verbose = verbose; }
void setSerialFrame(bool b) { m_serialFrame = b; }
void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
public slots:
void startInferior();
signals:
void output(const QString &senderName, const QString &data);
private slots:
void handleProcError(QProcess::ProcessError error);
void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
void handleProcStarted();
void handleProcStateChanged(QProcess::ProcessState newState);
void run();
void startGdb();
private:
friend class RunnerGui;
void connectProcess(QProcess *proc);
void sendOutput(QObject *sender, const QString &data);
void sendOutput(const QString &data) { sendOutput(0, data); }
QString m_rfcommDevice; // /dev/rfcomm0
QString m_gdbServerName; // 127.0.0.1:(2222+uid)
QProcess m_gdbProc;
QProcess m_rfcommProc;
bool m_running;
public:
//
// Implementation of GdbProcessBase
//
void start(const QString &program, const QStringList &args,
QIODevice::OpenMode mode = QIODevice::ReadWrite);
void kill();
void terminate();
bool waitForStarted(int msecs = 30000);
bool waitForFinished(int msecs = 30000);
QProcess::ProcessState state() const;
QString errorString() const;
QByteArray readAllStandardError();
QByteArray readAllStandardOutput();
qint64 write(const char *data);
void setWorkingDirectory(const QString &dir);
void setEnvironment(const QStringList &env);
//
// TRK
//
void sendTrkMessage(byte code,
TrkCallback callback = TrkCallback(),
const QByteArray &data = QByteArray(),
const QVariant &cookie = QVariant());
Q_SLOT void handleTrkResult(const trk::TrkResult &data);
Q_SLOT void handleTrkError(const QString &msg);
// convenience messages
void sendTrkAck(byte token);
void handleCpuType(const TrkResult &result);
void handleCreateProcess(const TrkResult &result);
void handleClearBreakpoint(const TrkResult &result);
void handleSignalContinue(const TrkResult &result);
void handleStop(const TrkResult &result);
void handleSupportMask(const TrkResult &result);
void handleTrkVersions(const TrkResult &result);
void handleDisconnect(const TrkResult &result);
void handleAndReportCreateProcess(const TrkResult &result);
void handleAndReportReadRegisters(const TrkResult &result);
QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const;
QByteArray trkContinueMessage();
QByteArray trkReadRegisterMessage();
QByteArray trkReadMemoryMessage(uint addr, uint len);
QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
void handleAndReportSetBreakpoint(const TrkResult &result);
void handleReadMemoryBuffered(const TrkResult &result);
void handleReadMemoryUnbuffered(const TrkResult &result);
void handleStepRange(const TrkResult &result);
void handleReadRegisters(const TrkResult &result);
void reportReadMemoryBuffered(const TrkResult &result);
void reportToGdb(const TrkResult &result);
// set breakpoints behind gdb's back
void handleSetTrkBreakpoint(const TrkResult &result);
void handleSetTrkMainBreakpoint(const TrkResult &result);
void readMemory(uint addr, uint len);
void interruptInferior();
trk::TrkDevice m_trkDevice;
//
// Gdb
//
struct GdbCommand
{
GdbCommand() : flags(0), callback(GdbCallback()), callbackName(0) {}
int flags;
GdbCallback callback;
const char *callbackName;
QString command;
QVariant cookie;
//QTime postTime;
};
void sendGdbMessage(const QString &msg,
GdbCallback callback = GdbCallback(),
const QVariant &cookie = QVariant());
Q_SLOT void handleGdbConnection();
Q_SLOT void readGdbServerCommand();
void readGdbResponse();
void handleGdbServerCommand(const QByteArray &cmd);
void sendGdbServerMessage(const QByteArray &msg,
const QByteArray &logNote = QByteArray());
void sendGdbServerMessageAfterTrkResponse(const QByteArray &msg,
const QByteArray &logNote = QByteArray());
void sendGdbServerAck();
bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
Q_SLOT void handleGdbReadyReadStandardError();
Q_SLOT void handleGdbReadyReadStandardOutput();
void logMessage(const QString &msg, bool force = false);
Q_SLOT void trkLogMessage(const QString &msg);
void handleInfoAddress(const GdbResult &result);
void handleInfoMainAddress(const GdbResult &result);
QTcpServer m_gdbServer;
QPointer<QTcpSocket> m_gdbConnection;
QByteArray m_gdbReadBuffer;
bool m_gdbAckMode;
QHash<int, GdbCommand> m_gdbCookieForToken;
//
// Rfcomm
//
Q_SLOT void handleRfcommReadyReadStandardError();
Q_SLOT void handleRfcommReadyReadStandardOutput();
// Debuggee state
Q_SLOT void executeCommand(const QString &msg);
trk::Session m_session; // global-ish data (process id, target information)
trk::Snapshot m_snapshot; // local-ish data (memory and registers)
int m_verbose;
bool m_serialFrame;
bool m_bufferedMemoryRead;
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_SYMBIANADAPTER_H

View File

@@ -0,0 +1,66 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#define QT_NO_CAST_FROM_ASCII
#include "gdb/gdbengine.h"
#include "symbianadapter.h"
//#include "debuggerdialogs.h"
#include <utils/qtcassert.h>
#include <texteditor/itexteditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QMetaObject>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtCore/QTextStream>
namespace Debugger {
namespace Internal {
IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
QList<Core::IOptionsPage*> *opts)
{
Q_UNUSED(opts);
//opts->push_back(new GdbOptionsPage);
return new GdbEngine(parent, new SymbianAdapter);
}
} // namespace Internal
} // namespace Debugger

View File

@@ -27,7 +27,7 @@
**
**************************************************************************/
#include "trkdevicex.h"
#include "trkclient.h"
#include "trkutils.h"
#include <QtCore/QString>
@@ -35,7 +35,6 @@
#include <QtCore/QQueue>
#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QSharedPointer>
#ifdef Q_OS_WIN
# include <windows.h>
@@ -117,14 +116,12 @@ struct TrkMessage
QByteArray data;
QVariant cookie;
Callback callback;
bool invokeOnNAK;
};
TrkMessage::TrkMessage(byte c, byte t, Callback cb) :
code(c),
token(t),
callback(cb),
invokeOnNAK(false)
callback(cb)
{
}
@@ -144,8 +141,7 @@ public:
// Enqueue messages.
void queueTrkMessage(byte code, Callback callback,
const QByteArray &data, const QVariant &cookie,
bool invokeOnNAK);
const QByteArray &data, const QVariant &cookie);
void queueTrkInitialPing();
// Call this from the device read notification with the results.
@@ -184,14 +180,13 @@ byte TrkWriteQueue::nextTrkWriteToken()
}
void TrkWriteQueue::queueTrkMessage(byte code, Callback callback,
const QByteArray &data, const QVariant &cookie, bool invokeOnNAK)
const QByteArray &data, const QVariant &cookie)
{
const byte token = code == TRK_WRITE_QUEUE_NOOP_CODE ?
byte(0) : nextTrkWriteToken();
TrkMessage msg(code, token, callback);
msg.data = data;
msg.cookie = cookie;
msg.invokeOnNAK = invokeOnNAK;
trkWriteQueue.append(msg);
}
@@ -233,16 +228,14 @@ void TrkWriteQueue::notifyWriteResult(bool ok)
void TrkWriteQueue::slotHandleResult(const TrkResult &result)
{
trkWriteBusy = false;
if (result.code != TrkNotifyAck && result.code != TrkNotifyNak)
return;
//if (result.code != TrkNotifyAck && result.code != TrkNotifyNak)
// return;
// Find which request the message belongs to and invoke callback
// if ACK or on NAK if desired.
const TokenMessageMap::iterator it = writtenTrkMessages.find(result.token);
if (it == writtenTrkMessages.end())
return;
const bool invokeCB = it.value().callback
&& (result.code == TrkNotifyAck || it.value().invokeOnNAK);
const bool invokeCB = it.value().callback;
if (invokeCB) {
TrkResult result1 = result;
result1.cookie = it.value().cookie;
@@ -257,8 +250,18 @@ void TrkWriteQueue::queueTrkInitialPing()
trkWriteQueue.append(TrkMessage(0, 0));
}
struct TrkDevicePrivate {
///////////////////////////////////////////////////////////////////////
//
// TrkDevicePrivate
//
///////////////////////////////////////////////////////////////////////
struct TrkDevicePrivate
{
TrkDevicePrivate();
TrkWriteQueue queue;
#ifdef Q_OS_WIN
HANDLE hdevice;
#else
@@ -298,11 +301,13 @@ TrkDevicePrivate::TrkDevicePrivate() :
TrkDevice::TrkDevice(QObject *parent) :
QObject(parent),
d(new TrkDevicePrivate),
qd(new TrkWriteQueue)
d(new TrkDevicePrivate)
{}
TrkDevice::~TrkDevice()
{
connect(this, SIGNAL(messageReceived(trk::TrkResult)),
this, SLOT(slotHandleResult(trk::TrkResult)));
close();
delete d;
}
bool TrkDevice::open(const QString &port, QString *errorMessage)
@@ -355,14 +360,6 @@ bool TrkDevice::open(const QString &port, QString *errorMessage)
#endif
}
TrkDevice::~TrkDevice()
{
close();
delete d;
delete qd;
}
void TrkDevice::close()
{
if (!isOpen())
@@ -492,6 +489,7 @@ void TrkDevice::tryTrkRead()
while (extractResult(&d->trkReadBuffer, d->serialFrame, &r, &rawData)) {
//if (verbose())
// logMessage("Read TrkResult " + r.data.toHex());
d->queue.slotHandleResult(r);
emit messageReceived(r);
if (!rawData.isEmpty())
emit rawDataReceived(rawData);
@@ -512,14 +510,14 @@ void TrkDevice::emitError(const QString &s)
}
void TrkDevice::sendTrkMessage(byte code, Callback callback,
const QByteArray &data, const QVariant &cookie, bool invokeOnNAK)
const QByteArray &data, const QVariant &cookie)
{
qd->queueTrkMessage(code, callback, data, cookie, invokeOnNAK);
d->queue.queueTrkMessage(code, callback, data, cookie);
}
void TrkDevice::sendTrkInitialPing()
{
qd->queueTrkInitialPing();
d->queue.queueTrkInitialPing();
}
bool TrkDevice::sendTrkAck(byte token)
@@ -535,10 +533,10 @@ bool TrkDevice::sendTrkAck(byte token)
void TrkDevice::tryTrkWrite()
{
TrkMessage message;
if (!qd->pendingMessage(&message))
if (!d->queue.pendingMessage(&message))
return;
const bool success = trkWriteRawMessage(message);
qd->notifyWriteResult(success);
d->queue.notifyWriteResult(success);
}
bool TrkDevice::trkWriteRawMessage(const TrkMessage &msg)
@@ -553,10 +551,5 @@ bool TrkDevice::trkWriteRawMessage(const TrkMessage &msg)
return rc;
}
void TrkDevice::slotHandleResult(const TrkResult &result)
{
qd->slotHandleResult(result);
}
} // namespace trk

View File

@@ -46,8 +46,6 @@ namespace trk {
struct TrkResult;
struct TrkMessage;
struct TrkDevicePrivate;
class TrkWriteQueue;
struct TrkWriteQueueIODevicePrivate;
/* TrkDevice: Implements a Windows COM or Linux device for
* Trk communications. Provides synchronous write and asynchronous
@@ -106,9 +104,7 @@ public:
void sendTrkMessage(unsigned char code,
Callback callBack = Callback(),
const QByteArray &data = QByteArray(),
const QVariant &cookie = QVariant(),
// Invoke callback on receiving NAK, too.
bool invokeOnNAK = false);
const QVariant &cookie = QVariant());
// Enqeue an initial ping
void sendTrkInitialPing();
@@ -116,15 +112,11 @@ public:
// Send an Ack synchronously, bypassing the queue
bool sendTrkAck(unsigned char token);
private slots:
void slotHandleResult(const trk::TrkResult &);
private:
void tryTrkWrite();
bool trkWriteRawMessage(const TrkMessage &msg);
TrkDevicePrivate *d;
TrkWriteQueue *qd;
};
} // namespace trk

View File

@@ -27,11 +27,14 @@
**
**************************************************************************/
#ifndef _TRK_FUNCTOR_H_
#define _TRK_FUNCTOR_H_
#ifndef DEBUGGER_TRK_FUNCTOR_H
#define DEBUGGER_TRK_FUNCTOR_H
#include <QtGlobal>
// FIXME: rename into something less TRK-specific
namespace trk {
namespace Internal {
/* Helper class for the 1-argument functor:

View File

@@ -43,6 +43,11 @@ QByteArray hexNumber(uint n, int digits)
return QByteArray(digits - ba.size(), '0') + ba;
}
QByteArray hexxNumber(uint n, int digits)
{
return "0x" + hexNumber(n, digits);
}
TrkResult::TrkResult() :
code(0),
token(0),
@@ -345,5 +350,16 @@ int TrkResult::errorCode() const
return errorCode;
return isNAK ? 0xff : 0;
}
QString TrkResult::errorString() const
{
// NAK means always error, else data sized 1 with a non-null element
if (code == 0xff)
return "NAK";
if (data.size() < 1)
return "Unknown error packet";
return errorMessage(data.at(0));
}
} // namespace trk

View File

@@ -72,6 +72,7 @@ enum Command {
QByteArray decode7d(const QByteArray &ba);
QByteArray encode7d(const QByteArray &ba);
inline byte extractByte(const char *data) { return *data; }
ushort extractShort(const char *data);
uint extractInt(const char *data);
@@ -143,7 +144,7 @@ struct Session
uint tid;
uint codeseg;
uint dataseg;
QHash<uint, uint> tokenToBreakpointIndex;
QHash<uint, uint> addressToBP;
// Gdb request
uint currentThread;
@@ -177,6 +178,7 @@ struct TrkResult
QString toString() const;
// 0 for no error.
int errorCode() const;
QString errorString() const;
byte code;
byte token;
@@ -192,9 +194,9 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame);
bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, QByteArray *rawData = 0);
QByteArray errorMessage(byte code);
QByteArray hexNumber(uint n, int digits = 0);
QByteArray hexxNumber(uint n, int digits = 0); // prepends '0x', too
uint swapEndian(uint in);
} // namespace trk
#endif // DEBUGGER_TRK_UTILS

View File

@@ -58,7 +58,13 @@ void AbstractProcessStep::setCommand(const QString &buildConfiguration, const QS
QString AbstractProcessStep::command(const QString &buildConfiguration) const
{
return value(buildConfiguration, PROCESS_COMMAND).toString();
QString result = value(buildConfiguration, PROCESS_COMMAND).toString();
if (QFileInfo(result).isRelative()) {
QString searchInPath = environment(buildConfiguration).searchInPath(result);
if (!searchInPath.isEmpty())
result = searchInPath;
}
return result;
}
void AbstractProcessStep::setWorkingDirectory(const QString &buildConfiguration, const QString &workingDirectory)

View File

@@ -344,12 +344,7 @@ QString QmlRunConfiguration::type() const
QString QmlRunConfiguration::executable() const
{
if (! QFile::exists(m_qmlViewer)) {
QMessageBox::information(Core::ICore::instance()->mainWindow(),
tr("QML Viewer"),
tr("Could not find the qmlviewer executable, please specify one."));
}
// No need to verify if the QML Viewer exists. The console will tell us anyway when we try to launch it.
return m_qmlViewer;
}

View File

@@ -93,7 +93,7 @@ bool BaseTextDocument::save(const QString &fileName)
cursor.beginEditBlock();
if (m_storageSettings.m_cleanWhitespace)
cleanWhitespace(cursor, m_storageSettings.m_inEntireDocument);
cleanWhitespace(cursor, m_storageSettings.m_cleanIndentation, m_storageSettings.m_inEntireDocument);
if (m_storageSettings.m_addFinalNewLine)
ensureFinalNewLine(cursor);
cursor.endEditBlock();
@@ -301,23 +301,28 @@ void BaseTextDocument::setSyntaxHighlighter(QSyntaxHighlighter *highlighter)
void BaseTextDocument::cleanWhitespace()
void BaseTextDocument::cleanWhitespace(const QTextCursor &cursor)
{
QTextCursor cursor(m_document);
cursor.beginEditBlock();
cleanWhitespace(cursor, true);
if (m_storageSettings.m_addFinalNewLine)
ensureFinalNewLine(cursor);
cursor.endEditBlock();
bool hasSelection = cursor.hasSelection();
QTextCursor copyCursor = cursor;
copyCursor.beginEditBlock();
cleanWhitespace(copyCursor, true, true);
if (!hasSelection)
ensureFinalNewLine(copyCursor);
copyCursor.endEditBlock();
}
void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool inEntireDocument)
void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument)
{
TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(m_document->documentLayout());
QTextBlock block = m_document->firstBlock();
while (block.isValid()) {
QTextBlock block = m_document->findBlock(cursor.selectionStart());
QTextBlock end;
if (cursor.hasSelection())
end = m_document->findBlock(cursor.selectionEnd()-1).next();
while (block.isValid() && block != end) {
if (inEntireDocument || block.revision() > documentLayout->lastSaveRevision) {
@@ -327,7 +332,7 @@ void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool inEntireDocumen
cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, trailing);
cursor.removeSelectedText();
}
if (m_storageSettings.m_cleanIndentation && !m_tabSettings.isIndentationClean(blockText)) {
if (cleanIndentation && !m_tabSettings.isIndentationClean(blockText)) {
cursor.setPosition(block.position());
int firstNonSpace = m_tabSettings.firstNonSpace(blockText);
if (firstNonSpace == blockText.length()) {

View File

@@ -110,7 +110,7 @@ public:
void reload(QTextCodec *codec);
void cleanWhitespace();
void cleanWhitespace(const QTextCursor &cursor);
signals:
void titleChanged(QString title);
@@ -146,7 +146,7 @@ private:
bool m_hasDecodingError;
QByteArray m_decodingErrorSample;
void cleanWhitespace(QTextCursor& cursor, bool onlyInModifiedLines);
void cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument);
void ensureFinalNewLine(QTextCursor& cursor);
};

View File

@@ -833,7 +833,7 @@ void BaseTextEditor::moveLineUpDown(bool up)
void BaseTextEditor::cleanWhitespace()
{
d->m_document->cleanWhitespace();
d->m_document->cleanWhitespace(textCursor());
}
void BaseTextEditor::keyPressEvent(QKeyEvent *e)
@@ -887,13 +887,18 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
QTextCursor cursor = textCursor();
if (d->m_inBlockSelectionMode)
cursor.clearSelection();
if (d->m_document->tabSettings().m_autoIndent) {
const TabSettings &ts = d->m_document->tabSettings();
if (ts.m_autoIndent) {
cursor.beginEditBlock();
cursor.insertBlock();
indent(document(), cursor, QChar::Null);
cursor.endEditBlock();
} else {
cursor.beginEditBlock();
QString previousBlockText = cursor.block().text();
cursor.insertBlock();
cursor.insertText(ts.indentationString(previousBlockText));
cursor.endEditBlock();
}
e->accept();
setTextCursor(cursor);
@@ -1337,6 +1342,16 @@ bool BaseTextEditor::codeFoldingSupported() const
return d->m_codeFoldingSupported;
}
void BaseTextEditor::setMouseNavigationEnabled(bool b)
{
d->m_mouseNavigationEnabled = b;
}
bool BaseTextEditor::mouseNavigationEnabled() const
{
return d->m_mouseNavigationEnabled;
}
void BaseTextEditor::setRevisionsVisible(bool b)
{
d->m_revisionsVisible = b;
@@ -1372,12 +1387,14 @@ BaseTextEditorPrivate::BaseTextEditorPrivate()
m_marksVisible(false),
m_codeFoldingVisible(false),
m_codeFoldingSupported(false),
m_mouseNavigationEnabled(true),
m_revisionsVisible(false),
m_lineNumbersVisible(true),
m_highlightCurrentLine(true),
m_requestMarkEnabled(true),
m_lineSeparatorsAllowed(false),
m_visibleWrapColumn(0),
m_showingLink(false),
m_editable(0),
m_actionHack(0),
m_inBlockSelectionMode(false),
@@ -2721,6 +2738,32 @@ void BaseTextEditorPrivate::clearVisibleCollapsedBlock()
void BaseTextEditor::mouseMoveEvent(QMouseEvent *e)
{
d->m_lastEventWasBlockSelectionEvent = (e->modifiers() & Qt::AltModifier);
bool linkFound = false;
if (d->m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier) {
// Link emulation behaviour for 'go to definition'
const QTextCursor cursor = cursorForPosition(e->pos());
// Check that the mouse was actually on the text somewhere
bool onText = cursorRect(cursor).right() >= e->x();
if (!onText) {
QTextCursor nextPos = cursor;
nextPos.movePosition(QTextCursor::Right);
onText = cursorRect(nextPos).right() >= e->x();
}
const Link link = findLinkAt(cursor, false);
if (onText && link.isValid()) {
showLink(link);
linkFound = true;
}
}
if (!linkFound)
clearLink();
if (e->buttons() == Qt::NoButton) {
const QTextBlock collapsedBlock = collapsedBlockAt(e->pos());
const int blockNumber = collapsedBlock.next().blockNumber();
@@ -2767,6 +2810,38 @@ void BaseTextEditor::mousePressEvent(QMouseEvent *e)
QPlainTextEdit::mousePressEvent(e);
}
void BaseTextEditor::mouseReleaseEvent(QMouseEvent *e)
{
if (d->m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier
&& !(e->modifiers() & Qt::ShiftModifier)
&& e->button() == Qt::LeftButton) {
const QTextCursor cursor = cursorForPosition(e->pos());
if (openLink(findLinkAt(cursor))) {
clearLink();
return;
}
}
QPlainTextEdit::mouseReleaseEvent(e);
}
void BaseTextEditor::leaveEvent(QEvent *e)
{
// Clear link emulation when the mouse leaves the editor
clearLink();
QPlainTextEdit::leaveEvent(e);
}
void BaseTextEditor::keyReleaseEvent(QKeyEvent *e)
{
// Clear link emulation when Ctrl is released
if (e->key() == Qt::Key_Control)
clearLink();
QPlainTextEdit::keyReleaseEvent(e);
}
void BaseTextEditor::extraAreaLeaveEvent(QEvent *)
{
// fake missing mouse move event from Qt
@@ -2833,7 +2908,7 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
document()->findBlockByNumber(d->m_highlightBlocksInfo.open.last()).position()
);
QTextBlock c = cursor.block();
if (!TextBlockUserData::canCollapse(c))
if (TextBlockUserData::hasCollapseAfter(c.previous()))
c = c.previous();
toggleBlockVisible(c);
d->moveCursorVisible(false);
@@ -3119,17 +3194,14 @@ void BaseTextEditor::handleBackspaceKey()
continue;
previousIndent = tabSettings.columnAt(previousNonEmptyBlockText,
tabSettings.firstNonSpace(previousNonEmptyBlockText));
if (previousIndent < indent)
if (previousIndent < indent) {
cursor.beginEditBlock();
cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor);
cursor.insertText(tabSettings.indentationString(previousNonEmptyBlockText));
cursor.endEditBlock();
break;
}
}
if (previousIndent >= indent)
previousIndent = 0;
cursor.beginEditBlock();
cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor);
cursor.insertText(tabSettings.indentationString(0, previousIndent));
cursor.endEditBlock();
}
void BaseTextEditor::wheelEvent(QWheelEvent *e)
@@ -3186,6 +3258,50 @@ void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar
}
}
BaseTextEditor::Link BaseTextEditor::findLinkAt(const QTextCursor &, bool)
{
return Link();
}
bool BaseTextEditor::openLink(const Link &link)
{
if (link.fileName.isEmpty())
return false;
if (baseTextDocument()->fileName() == link.fileName) {
Core::EditorManager *editorManager = Core::EditorManager::instance();
editorManager->addCurrentPositionToNavigationHistory();
gotoLine(link.line, link.column);
setFocus();
return true;
}
return openEditorAt(link.fileName, link.line, link.column);
}
void BaseTextEditor::showLink(const Link &link)
{
QTextEdit::ExtraSelection sel;
sel.cursor = textCursor();
sel.cursor.setPosition(link.pos);
sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor);
sel.format = d->m_linkFormat;
sel.format.setFontUnderline(true);
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel);
viewport()->setCursor(Qt::PointingHandCursor);
d->m_showingLink = true;
}
void BaseTextEditor::clearLink()
{
if (!d->m_showingLink)
return;
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
viewport()->setCursor(Qt::IBeamCursor);
d->m_showingLink = false;
}
void BaseTextEditorPrivate::updateMarksBlock(const QTextBlock &block)
{
if (const TextBlockUserData *userData = TextEditDocumentLayout::testUserData(block))
@@ -4005,8 +4121,8 @@ void BaseTextEditor::unCommentSelection()
void BaseTextEditor::showEvent(QShowEvent* e)
{
if (!d->m_fontSettings.isEmpty()) {
setFontSettings(d->m_fontSettings);
d->m_fontSettings.clear();
setFontSettings(d->m_fontSettings);
d->m_fontSettings.clear();
}
QPlainTextEdit::showEvent(e);
}
@@ -4015,11 +4131,12 @@ void BaseTextEditor::showEvent(QShowEvent* e)
void BaseTextEditor::setFontSettingsIfVisible(const TextEditor::FontSettings &fs)
{
if (!isVisible()) {
d->m_fontSettings = fs;
return;
d->m_fontSettings = fs;
return;
}
setFontSettings(fs);
}
void BaseTextEditor::setFontSettings(const TextEditor::FontSettings &fs)
{
const QTextCharFormat textFormat = fs.toTextCharFormat(QLatin1String(Constants::C_TEXT));
@@ -4030,6 +4147,7 @@ void BaseTextEditor::setFontSettings(const TextEditor::FontSettings &fs)
const QTextCharFormat parenthesesFormat = fs.toTextCharFormat(QLatin1String(Constants::C_PARENTHESES));
d->m_currentLineFormat = fs.toTextCharFormat(QLatin1String(Constants::C_CURRENT_LINE));
d->m_currentLineNumberFormat = fs.toTextCharFormat(QLatin1String(Constants::C_CURRENT_LINE_NUMBER));
d->m_linkFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_LINK));
d->m_ifdefedOutFormat = fs.toTextCharFormat(QLatin1String(Constants::C_DISABLED_CODE));
QFont font(textFormat.font());
@@ -4082,6 +4200,7 @@ void BaseTextEditor::setDisplaySettings(const DisplaySettings &ds)
setCodeFoldingVisible(ds.m_displayFoldingMarkers);
setHighlightCurrentLine(ds.m_highlightCurrentLine);
setRevisionsVisible(ds.m_markTextChanges);
setMouseNavigationEnabled(ds.m_mouseNavigation);
if (d->m_displaySettings.m_visualizeWhitespace != ds.m_visualizeWhitespace) {
if (QSyntaxHighlighter *highlighter = baseTextDocument()->syntaxHighlighter())

View File

@@ -145,13 +145,10 @@ public:
inline static bool hasCollapseAfter(const QTextBlock & block)
{
if (!block.isValid())
return false;
TextBlockUserData *data = static_cast<TextBlockUserData*>(block.userData());
if (data && data->collapseMode() != NoCollapse) {
if (!block.isValid()) {
return false;
} else if (block.next().isValid()) {
data = static_cast<TextBlockUserData*>(block.next().userData());
TextBlockUserData *data = static_cast<TextBlockUserData*>(block.next().userData());
if (data && data->collapseMode() == TextBlockUserData::CollapseThis && !data->m_ifdefedOut)
return true;
}
@@ -277,8 +274,7 @@ private:
};
class TEXTEDITOR_EXPORT BaseTextEditor
: public QPlainTextEdit
class TEXTEDITOR_EXPORT BaseTextEditor : public QPlainTextEdit
{
Q_OBJECT
@@ -348,6 +344,9 @@ public:
void setCodeFoldingSupported(bool b);
bool codeFoldingSupported() const;
void setMouseNavigationEnabled(bool b);
bool mouseNavigationEnabled() const;
void setRevisionsVisible(bool b);
bool revisionsVisible() const;
@@ -499,14 +498,54 @@ protected:
void timerEvent(QTimerEvent *);
void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
void leaveEvent(QEvent *);
void keyReleaseEvent(QKeyEvent *);
// Rertuns true if key triggers an indent.
// Returns true if key triggers an indent.
virtual bool isElectricCharacter(const QChar &ch) const;
// Indent a text block based on previous line. Default does nothing
virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
// Indent at cursor. Calls indentBlock for selection or current line.
virtual void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
struct Link
{
Link(const QString &fileName = QString(),
int line = 0,
int column = 0)
: pos(-1)
, length(-1)
, fileName(fileName)
, line(line)
, column(column)
{}
bool isValid() const
{ return !(pos == -1 || length == -1); }
int pos; // Link position
int length; // Link length
QString fileName; // Target file
int line; // Target line
int column; // Target column
};
/*!
Reimplement this function to enable code navigation.
\a resolveTarget is set to true when the target of the link is relevant
(it isn't until the link is used).
*/
virtual Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
/*!
Reimplement this function if you want to customize the way a link is
opened. Returns whether the link was opened succesfully.
*/
virtual bool openLink(const Link &link);
protected slots:
virtual void slotUpdateExtraAreaWidth();
virtual void slotModificationChanged(bool);
@@ -540,6 +579,8 @@ private:
QTextBlock collapsedBlockAt(const QPoint &pos, QRect *box = 0) const;
void showLink(const Link &);
void clearLink();
// parentheses matcher
private slots:

View File

@@ -194,6 +194,7 @@ public:
uint m_marksVisible : 1;
uint m_codeFoldingVisible : 1;
uint m_codeFoldingSupported : 1;
uint m_mouseNavigationEnabled : 1;
uint m_revisionsVisible : 1;
uint m_lineNumbersVisible : 1;
uint m_highlightCurrentLine : 1;
@@ -201,6 +202,9 @@ public:
uint m_lineSeparatorsAllowed : 1;
int m_visibleWrapColumn;
QTextCharFormat m_linkFormat;
bool m_showingLink;
QTextCharFormat m_ifdefedOutFormat;
QRegExp m_searchExpr;
@@ -226,7 +230,7 @@ public:
QString copyBlockSelection();
void removeBlockSelection(const QString &text = QString());
bool m_moveLineUndoHack;
QTextCursor m_findScope;
QTextCursor m_selectBlockAnchor;

View File

@@ -110,6 +110,18 @@ int TabSettings::firstNonSpace(const QString &text) const
return i;
}
QString TabSettings::indentationString(const QString &text) const
{
return text.left(firstNonSpace(text));
}
int TabSettings::indentationColumn(const QString &text) const
{
return columnAt(text, firstNonSpace(text));
}
int TabSettings::trailingWhitespaces(const QString &text) const
{
int i = 0;
@@ -225,7 +237,7 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const
const int oldBlockLength = text.size();
// Quickly check whether indenting is required.
if (oldBlockLength == 0 && newIndent == 0)
if (indentationColumn(text) == newIndent)
return;
const QString indentString = indentationString(0, newIndent);
@@ -234,12 +246,6 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const
if (oldBlockLength == indentString.length() && text == indentString)
return;
if (oldBlockLength > indentString.length() &&
text.startsWith(indentString) &&
!text.at(indentString.length()).isSpace()) {
return;
}
QTextCursor cursor(block);
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfBlock);

View File

@@ -63,6 +63,8 @@ struct TEXTEDITOR_EXPORT TabSettings
int spacesLeftFromPosition(const QString &text, int position) const;
int indentedColumn(int column, bool doIndent = true) const;
QString indentationString(int startColumn, int targetColumn) const;
QString indentationString(const QString &text) const;
int indentationColumn(const QString &text) const;
void indentLine(QTextBlock block, int newIndent) const;

View File

@@ -1139,10 +1139,11 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
}
if (!qmake_cache.isEmpty()) {
qmake_cache = QDir::cleanPath(qmake_cache);
if (evaluateFileInto(qmake_cache, &m_option->cache_valuemap, 0)) {
QHash<QString, QStringList> cache_valuemap;
if (evaluateFileInto(qmake_cache, &cache_valuemap, 0)) {
m_option->cachefile = qmake_cache;
if (m_option->qmakespec.isEmpty()) {
const QStringList &vals = m_option->cache_valuemap.value(QLatin1String("QMAKESPEC"));
const QStringList &vals = cache_valuemap.value(QLatin1String("QMAKESPEC"));
if (!vals.isEmpty())
m_option->qmakespec = vals.first();
}
@@ -1196,8 +1197,9 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
if (!evaluateFileInto(spec,
&m_option->base_valuemap, &m_option->base_functions)) {
errorMessage(format("Could not read qmake configuration file %1").arg(spec));
} else {
evaluateFileInto(qmake_cache, &m_option->base_valuemap, 0);
} else if (!m_option->cachefile.isEmpty()) {
evaluateFileInto(m_option->cachefile,
&m_option->base_valuemap, &m_option->base_functions);
}
}

View File

@@ -88,8 +88,7 @@ public:
friend class ProFileEvaluator;
friend class ProFileEvaluator::Private;
static QString field_sep; // Just a cache for quick construction
QHash<QString, QStringList> cache_valuemap; // Cached results of .qmake.cache
QHash<QString, QStringList> base_valuemap; // ~ and qmake.conf and default_pre.prf
QHash<QString, QStringList> base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf
FunctionDefs base_functions;
QStringList feature_roots;
};

View File

@@ -1,14 +1,20 @@
TEMPLATE = app
DEBUGGERHOME = ../../../src/plugins/debugger/symbian
INCLUDEPATH *= $$DEBUGGERHOME
UTILSDIR = ../../../src/libs
QT = core network
win32:CONFIG+=console
HEADERS += trkutils.h \
trkfunctor.h \
trkdevice.h \
HEADERS += \
$$DEBUGGERHOME/trkutils.h \
$$DEBUGGERHOME/trkfunctor.h \
$$PWD/trkdevice.h \
SOURCES += \
adapter.cpp \
trkutils.cpp \
trkdevice.cpp
$$DEBUGGERHOME/trkutils.cpp \
$$PWD/trkdevice.cpp \
$$PWD/adapter.cpp \

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,21 @@
TEMPLATE = app
DEBUGGERHOME = ../../../src/plugins/debugger/symbian
INCLUDEPATH *= $$DEBUGGERHOME
QT += network
win32:CONFIG+=console
HEADERS += \
trkutils.h \
trkdevicex.h \
$$DEBUGGERHOME/../gdb/gdbprocessbase.h \
$$DEBUGGERHOME/trkutils.h \
$$DEBUGGERHOME/trkclient.h \
$$DEBUGGERHOME/symbianadapter.h \
SOURCES += \
runner.cpp \
trkutils.cpp \
trkdevicex.cpp \
$$DEBUGGERHOME/trkutils.cpp \
$$DEBUGGERHOME/trkclient.cpp \
$$DEBUGGERHOME/symbianadapter.cpp \
$$PWD/runner.cpp \

View File

@@ -111,7 +111,7 @@ public:
explicit TrkWriteQueueDevice(QObject *parent = 0);
virtual ~TrkWriteQueueDevice();
// Construct as 'TrkWriteQueueDevice::Callback(instance, &Klass::method);'
// Construct as 'TrkWriteQueueDevice::Callback(instance, &Class::method);'
typedef TrkFunctor1<const TrkResult &> Callback;
// Enqueue a message with a notification callback.

View File

@@ -1,9 +1,15 @@
DEFINES += DEBUG_TRK=0
INCLUDEPATH *= $$PWD
SOURCES += $$PWD/launcher.cpp \
$$PWD/trkutils.cpp \
$$PWD/trkdevice.cpp
HEADERS += $$PWD/trkutils.h \
$$PWD/trkfunctor.h \
DEBUGGERHOME = ../../../src/plugins/debugger/symbian
INCLUDEPATH *= $$DEBUGGERHOME
SOURCES += \
$$DEBUGGERHOME/trkutils.cpp \
$$PWD/trkdevice.cpp \
$$PWD/launcher.cpp \
HEADERS += \
$$DEBUGGERHOME/trkutils.h \
$$DEBUGGERHOME/trkfunctor.h \
$$PWD/trkdevice.h \
$$PWD/launcher.h

View File

@@ -1,12 +1,17 @@
TEMPLATE = app
DEBUGGERHOME = ../../../src/plugins/debugger/symbian
QT = core network
win32:CONFIG+=console
INCLUDEPATH *= $$DEBUGGERHOME
HEADERS += \
trkutils.h
$$DEBUGGERHOME/trkutils.h
SOURCES += \
trkutils.cpp \
trkserver.cpp
$$DEBUGGERHOME/trkutils.cpp \
$$PWD/trkserver.cpp