forked from qt-creator/qt-creator
Merge branch 'master' of ../mainline into dui-editor
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
IDE_BUILD_TREE = $$OUT_PWD/..
|
||||
|
||||
include(../qtcreator.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 117 KiB |
@@ -37,9 +37,9 @@
|
||||
files and classes using minimal keystrokes.
|
||||
\o \bold{Support for qmake's .pro file format}: The project's \c{.pro}
|
||||
file is used as a project description file.
|
||||
\o \bold{Debugging Interface to GDB}: Applications can be debugged
|
||||
\o \bold{Debugging Interface}: Applications can be debugged
|
||||
within Qt Creator using a graphical frontend to the GNU symbolic
|
||||
debugger.
|
||||
debugger (GDB) and the Microsoft Console Debugger (CDB).
|
||||
\endlist
|
||||
\endtable
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
\o \l{Debugging with Qt Creator}
|
||||
\o \l{CMake Support in Qt Creator}
|
||||
\o \l{Support for Generic Projects in Qt Creator}
|
||||
\o \l{Handling External Libraries}
|
||||
\o \l{Tips and Tricks}
|
||||
\o \l{Keyboard Shortcuts}
|
||||
\o \l{Glossary}
|
||||
@@ -694,7 +695,6 @@
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\contentspage index.html
|
||||
\previouspage creator-writing-program.html
|
||||
@@ -1072,7 +1072,7 @@
|
||||
|
||||
Here, you can lock or unlock the location of your views as well as display
|
||||
or hide them. Among the views you can display are \gui Breakpoints,
|
||||
\gui Disassembler, \gui Modules, \gui Registers, \gui Gdb, \gui Stack, and
|
||||
\gui Disassembler, \gui Modules, \gui Registers, \gui Debugger, \gui Stack, and
|
||||
\gui Thread. The position of your dock widgets will be saved for future
|
||||
sessions.
|
||||
|
||||
@@ -1358,7 +1358,7 @@
|
||||
\contentspage index.html
|
||||
\previouspage creator-debugging.html
|
||||
\page creator-cmake-support.html
|
||||
\nextpage creator-tips.html
|
||||
\nextpage creator-generic-projects.html
|
||||
|
||||
\title CMake Support in Qt Creator
|
||||
|
||||
@@ -1412,7 +1412,7 @@
|
||||
\contentspage index.html
|
||||
\previouspage creator-cmake-support.html
|
||||
\page creator-generic-projects.html
|
||||
\nextpage creator-tips.html
|
||||
\nextpage creator-external-library-handling.html
|
||||
|
||||
\title Support for Generic Projects in Qt Creator
|
||||
|
||||
@@ -1428,10 +1428,65 @@
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\contentspage index.html
|
||||
\previouspage creator-generic-projects.html
|
||||
\page creator-external-library-handling.html
|
||||
\nextpage creator-tips.html
|
||||
|
||||
\title Handling External Libraries
|
||||
|
||||
Knowing external libraries is not only important for the
|
||||
underlying build system, but also for Qt Creator itself.
|
||||
This way, it can support code completion and syntax highlighting
|
||||
for external libraries as if they were part of the current
|
||||
project or the Qt library.
|
||||
|
||||
The way to add a library to the project depends on the
|
||||
project type, which influcences the build system used.
|
||||
The following sections describe the the procedure required
|
||||
for each project type.
|
||||
|
||||
\section1 QMake Projects (the default)
|
||||
|
||||
Open your your (ending in \c{.pro}) file from the
|
||||
\gui{Projects} pane, which will now show up in the editor.
|
||||
Follow the description in the
|
||||
\l{http://doc.qtsoftware.com/latest/make-project-files.html#declaring-other-libraries}
|
||||
{Declaring other Libraries} section of the Qt documentation.
|
||||
|
||||
If your project does sucessfully build and link against
|
||||
the external library, syntax completion and highlighting
|
||||
should also work.
|
||||
|
||||
\section1 CMake Projects
|
||||
|
||||
In CMake, libaries are usually detected using the \c{FIND_PACKAGE()} macro.
|
||||
A couple of them are already being shipped with CMake, they can be found in
|
||||
the \c{Modules} directory of your CMake installation. If you provide
|
||||
libraries on your own, you will need to provide your own \c{FindFoo.cmake}
|
||||
file. Refer to the \l{http://vtk.org/Wiki/CMake_FAQ#Writing_FindXXX.cmake_files}
|
||||
{CMake FAQ} for details.
|
||||
|
||||
As with qmake project, syntax completion and highlighting should work if
|
||||
you can sucessfully build and link against the external library.
|
||||
|
||||
\section1 Generic Projects
|
||||
|
||||
If you import a project using the \e{Generic Projects} function, Qt Creator will
|
||||
create a file called \c{<projectname>.includes} in your project root directory. It will
|
||||
contain all project subdirectories it that was able to find relevant header files in.
|
||||
Simply add your include pathes there.
|
||||
|
||||
Note that in Generic Project mode, Qt Creator will refrain from touching any
|
||||
project settings, so the above is merely a hint for the code completion and
|
||||
the syntax highlighter.
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\contentspage index.html
|
||||
\previouspage creator-debugging.html
|
||||
\previouspage creator-external-library-handling.html
|
||||
\page creator-tips.html
|
||||
\nextpage creator-keyboard-shortcuts.html
|
||||
|
||||
@@ -1526,6 +1581,9 @@
|
||||
\row
|
||||
\o Go to a line
|
||||
\o Ctrl + L
|
||||
\row
|
||||
\o Navigate between pages
|
||||
\o Alt + Left, Alt + Right
|
||||
\row
|
||||
\o Start debugging
|
||||
\o F5
|
||||
@@ -1734,4 +1792,3 @@
|
||||
QtCreator/src/shared/cplusplus
|
||||
\endlist
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
IDE_SOURCE_TREE = $$PWD
|
||||
|
||||
defineReplace(cleanPath) {
|
||||
win32:1 ~= s|\\\\|/|g
|
||||
contains(1, ^/.*):pfx = /
|
||||
@@ -18,6 +16,19 @@ defineReplace(targetPath) {
|
||||
return($$1)
|
||||
}
|
||||
|
||||
# For use in custom compilers which just copy files
|
||||
win32:i_flag = i
|
||||
defineReplace(stripSrcDir) {
|
||||
win32 {
|
||||
!contains(1, ^.:.*):1 = $$OUT_PWD/$$1
|
||||
} else {
|
||||
!contains(1, ^/.*):1 = $$OUT_PWD/$$1
|
||||
}
|
||||
out = $$cleanPath($$1)
|
||||
out ~= s|^$$re_escape($$PWD/)||$$i_flag
|
||||
return($$out)
|
||||
}
|
||||
|
||||
isEmpty(TEST):CONFIG(debug, debug|release) {
|
||||
!debug_and_release|build_pass {
|
||||
TEST = 1
|
||||
@@ -35,18 +46,23 @@ equals(TEST, 1) {
|
||||
DEFINES += WITH_TESTS
|
||||
}
|
||||
|
||||
isEmpty(IDE_BUILD_TREE) {
|
||||
error("qtcreator.pri: including file must define IDE_BUILD_TREE (probably a relative path)")
|
||||
}
|
||||
IDE_BUILD_TREE = $$cleanPath($$IDE_BUILD_TREE)
|
||||
IDE_SOURCE_TREE = $$PWD
|
||||
sub_dir = $$_PRO_FILE_PWD_
|
||||
sub_dir ~= s,^$$re_escape($$PWD),,
|
||||
IDE_BUILD_TREE = $$cleanPath($$OUT_PWD)
|
||||
IDE_BUILD_TREE ~= s,$$re_escape($$sub_dir)$,,
|
||||
IDE_APP_PATH = $$IDE_BUILD_TREE/bin
|
||||
macx {
|
||||
IDE_APP_TARGET = QtCreator
|
||||
IDE_LIBRARY_PATH = $$IDE_BUILD_TREE/bin/$${IDE_APP_TARGET}.app/Contents/PlugIns
|
||||
IDE_LIBRARY_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/PlugIns
|
||||
IDE_PLUGIN_PATH = $$IDE_LIBRARY_PATH
|
||||
IDE_DATA_PATH = $$IDE_BUILD_TREE/bin/$${IDE_APP_TARGET}.app/Contents/Resources
|
||||
IDE_LIBEXEC_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/Resources
|
||||
IDE_DATA_PATH = $$IDE_APP_PATH/$${IDE_APP_TARGET}.app/Contents/Resources
|
||||
contains(QT_CONFIG, ppc):CONFIG += ppc x86
|
||||
copydata = 1
|
||||
} else {
|
||||
win32 {
|
||||
contains(TEMPLATE, vc.*)|contains(TEMPLATE_PREFIX, vc):vcproj = 1
|
||||
IDE_APP_TARGET = qtcreator
|
||||
} else {
|
||||
IDE_APP_WRAPPER = qtcreator
|
||||
@@ -54,9 +70,10 @@ macx {
|
||||
}
|
||||
IDE_LIBRARY_PATH = $$IDE_BUILD_TREE/$$IDE_LIBRARY_BASENAME/qtcreator
|
||||
IDE_PLUGIN_PATH = $$IDE_LIBRARY_PATH/plugins
|
||||
IDE_LIBEXEC_PATH = $$IDE_APP_PATH # FIXME
|
||||
IDE_DATA_PATH = $$IDE_BUILD_TREE/share/qtcreator
|
||||
!isEqual(IDE_SOURCE_TREE, $$IDE_BUILD_TREE):copydata = 1
|
||||
}
|
||||
IDE_APP_PATH = $$IDE_BUILD_TREE/bin
|
||||
|
||||
INCLUDEPATH += \
|
||||
$$IDE_SOURCE_TREE/src/libs \
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#version check qt
|
||||
TOO_OLD_LIST=$$find(QT_VERSION, ^4\.[0-4])
|
||||
count(TOO_OLD_LIST, 1) {
|
||||
message("Cannot build the Qt Creator with a Qt version that old:" $$QT_VERSION)
|
||||
contains(QT_VERSION, ^4\.[0-4]\..*) {
|
||||
message("Cannot build Qt Creator with Qt version $$QT_VERSION.")
|
||||
error("Use at least Qt 4.5.")
|
||||
}
|
||||
|
||||
include(qtcreator.pri)
|
||||
include(doc/doc.pri)
|
||||
|
||||
TEMPLATE = subdirs
|
||||
CONFIG += ordered
|
||||
|
||||
SUBDIRS = src share
|
||||
unix:!macx:!equals(_PRO_FILE_PWD_, $$OUT_PWD):SUBDIRS += bin
|
||||
unix:!macx:!isEmpty(copydata):SUBDIRS += bin
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
IDE_BUILD_TREE = $$OUT_PWD/../..
|
||||
|
||||
include(../../qtcreator.pri)
|
||||
|
||||
win32:i_flag = i
|
||||
defineReplace(stripSrcDir) {
|
||||
win32 {
|
||||
!contains(1, ^.:.*):1 = $$OUT_PWD/$$1
|
||||
} else {
|
||||
!contains(1, ^/.*):1 = $$OUT_PWD/$$1
|
||||
}
|
||||
out = $$cleanPath($$1)
|
||||
out ~= s|^$$re_escape($$PWD/)||$$i_flag
|
||||
return($$out)
|
||||
}
|
||||
|
||||
contains(TEMPLATE, vc.*)|contains(TEMPLATE_PREFIX, vc):vcproj = 1
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = phony_target
|
||||
|
||||
@@ -39,7 +23,7 @@ DATA_DIRS = \
|
||||
schemes \
|
||||
gdbmacros
|
||||
|
||||
macx|!equals(_PRO_FILE_PWD_, $$OUT_PWD) {
|
||||
!isEmpty(copydata) {
|
||||
|
||||
for(data_dir, DATA_DIRS) {
|
||||
files = $$files($$PWD/$$data_dir/*.*, true)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
IDE_BUILD_TREE = $$OUT_PWD/../../..
|
||||
include(../../../qtcreator.pri)
|
||||
|
||||
TRANSLATIONS = de ja
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
IDE_BUILD_TREE = $$OUT_PWD/../..
|
||||
|
||||
include(../../qtcreator.pri)
|
||||
include(../shared/qtsingleapplication/qtsingleapplication.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = $$IDE_APP_TARGET
|
||||
DESTDIR = ../../bin
|
||||
DESTDIR = $$IDE_APP_PATH
|
||||
|
||||
|
||||
SOURCES += main.cpp
|
||||
|
||||
86
src/libs/utils/consoleprocess.cpp
Normal file
86
src/libs/utils/consoleprocess.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** 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)
|
||||
**
|
||||
** 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 qt-sales@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "consoleprocess.h"
|
||||
|
||||
namespace Core {
|
||||
namespace Utils {
|
||||
|
||||
QString ConsoleProcess::modeOption(Mode m)
|
||||
{
|
||||
switch (m) {
|
||||
case Debug:
|
||||
return QLatin1String("debug");
|
||||
case Suspend:
|
||||
return QLatin1String("suspend");
|
||||
case Run:
|
||||
break;
|
||||
}
|
||||
return QLatin1String("run");
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgCommChannelFailed(const QString &error)
|
||||
{
|
||||
return tr("Cannot set up communication channel: %1").arg(error);
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgPromptToClose()
|
||||
{
|
||||
//! Showed in a terminal which might have
|
||||
//! a different character set on Windows.
|
||||
return tr("Press <RETURN> to close this window...");
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgCannotCreateTempFile(const QString &why)
|
||||
{
|
||||
return tr("Cannot create temporary file: %1").arg(why);
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgCannotCreateTempDir(const QString & dir, const QString &why)
|
||||
{
|
||||
return tr("Cannot create temporary directory '%1': %2").arg(dir, why);
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgUnexpectedOutput()
|
||||
{
|
||||
return tr("Unexpected output from helper program.");
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgCannotChangeToWorkDir(const QString & dir, const QString &why)
|
||||
{
|
||||
return tr("Cannot change to working directory '%1': %2").arg(dir, why);
|
||||
}
|
||||
|
||||
QString ConsoleProcess::msgCannotExecute(const QString & p, const QString &why)
|
||||
{
|
||||
return tr("Cannot execute '%1': %2").arg(p, why);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -59,14 +59,15 @@ class QWORKBENCH_UTILS_EXPORT ConsoleProcess : public QObject, public AbstractPr
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Mode { Run, Debug, Suspend };
|
||||
ConsoleProcess(QObject *parent = 0);
|
||||
~ConsoleProcess();
|
||||
|
||||
bool start(const QString &program, const QStringList &args);
|
||||
void stop();
|
||||
|
||||
void setDebug(bool on) { m_debug = on; }
|
||||
bool isDebug() const { return m_debug; }
|
||||
void setMode(Mode m) { m_mode = m; }
|
||||
Mode mode() const { return m_mode; }
|
||||
|
||||
bool isRunning() const; // This reflects the state of the console+stub
|
||||
qint64 applicationPID() const { return m_appPid; }
|
||||
@@ -99,6 +100,15 @@ private slots:
|
||||
#endif
|
||||
|
||||
private:
|
||||
static QString modeOption(Mode m);
|
||||
static QString msgCommChannelFailed(const QString &error);
|
||||
static QString msgPromptToClose();
|
||||
static QString msgCannotCreateTempFile(const QString &why);
|
||||
static QString msgCannotCreateTempDir(const QString & dir, const QString &why);
|
||||
static QString msgUnexpectedOutput();
|
||||
static QString msgCannotChangeToWorkDir(const QString & dir, const QString &why);
|
||||
static QString msgCannotExecute(const QString & p, const QString &why);
|
||||
|
||||
QString stubServerListen();
|
||||
void stubServerShutdown();
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -106,7 +116,7 @@ private:
|
||||
void cleanupInferior();
|
||||
#endif
|
||||
|
||||
bool m_debug;
|
||||
Mode m_mode;
|
||||
qint64 m_appPid;
|
||||
int m_appCode;
|
||||
QString m_executable;
|
||||
|
||||
@@ -44,14 +44,13 @@
|
||||
|
||||
using namespace Core::Utils;
|
||||
|
||||
ConsoleProcess::ConsoleProcess(QObject *parent)
|
||||
: QObject(parent)
|
||||
ConsoleProcess::ConsoleProcess(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_mode(Run),
|
||||
m_appPid(0),
|
||||
m_stubSocket(0),
|
||||
m_settings(0)
|
||||
{
|
||||
m_debug = false;
|
||||
m_appPid = 0;
|
||||
m_stubSocket = 0;
|
||||
m_settings = 0;
|
||||
|
||||
connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
|
||||
|
||||
m_process.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
@@ -69,9 +68,9 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
|
||||
if (isRunning())
|
||||
return false;
|
||||
|
||||
QString err = stubServerListen();
|
||||
const QString err = stubServerListen();
|
||||
if (!err.isEmpty()) {
|
||||
emit processError(tr("Cannot set up communication channel: %1").arg(err));
|
||||
emit processError(msgCommChannelFailed(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,7 +78,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
|
||||
m_tempFile = new QTemporaryFile();
|
||||
if (!m_tempFile->open()) {
|
||||
stubServerShutdown();
|
||||
emit processError(tr("Cannot create temporary file: %1").arg(m_tempFile->errorString()));
|
||||
emit processError(msgCannotCreateTempFile(m_tempFile->errorString()));
|
||||
delete m_tempFile;
|
||||
m_tempFile = 0;
|
||||
return false;
|
||||
@@ -94,13 +93,13 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
|
||||
QStringList xtermArgs = terminalEmulator(m_settings).split(QLatin1Char(' ')); // FIXME: quoting
|
||||
xtermArgs
|
||||
#ifdef Q_OS_MAC
|
||||
<< (QCoreApplication::applicationDirPath() + "/../Resources/qtcreator_process_stub")
|
||||
<< (QCoreApplication::applicationDirPath() + QLatin1String("/../Resources/qtcreator_process_stub"))
|
||||
#else
|
||||
<< (QCoreApplication::applicationDirPath() + "/qtcreator_process_stub")
|
||||
<< (QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_process_stub"))
|
||||
#endif
|
||||
<< (m_debug ? "debug" : "exec")
|
||||
<< modeOption(m_mode)
|
||||
<< m_stubServer.fullServerName()
|
||||
<< tr("Press <RETURN> to close this window...")
|
||||
<< msgPromptToClose()
|
||||
<< workingDirectory()
|
||||
<< (m_tempFile ? m_tempFile->fileName() : 0)
|
||||
<< program << args;
|
||||
@@ -145,7 +144,7 @@ QString ConsoleProcess::stubServerListen()
|
||||
{
|
||||
QTemporaryFile tf;
|
||||
if (!tf.open())
|
||||
return tr("Cannot create temporary file: %1").arg(tf.errorString());
|
||||
return msgCannotCreateTempFile(tf.errorString());
|
||||
stubFifoDir = QFile::encodeName(tf.fileName());
|
||||
}
|
||||
// By now the temp file was deleted again
|
||||
@@ -153,9 +152,9 @@ QString ConsoleProcess::stubServerListen()
|
||||
if (!::mkdir(m_stubServerDir.constData(), 0700))
|
||||
break;
|
||||
if (errno != EEXIST)
|
||||
return tr("Cannot create temporary directory '%1': %2").arg(stubFifoDir, strerror(errno));
|
||||
return msgCannotCreateTempDir(stubFifoDir, QString::fromLocal8Bit(strerror(errno)));
|
||||
}
|
||||
QString stubServer = stubFifoDir + "/stub-socket";
|
||||
const QString stubServer = stubFifoDir + "/stub-socket";
|
||||
if (!m_stubServer.listen(stubServer)) {
|
||||
::rmdir(m_stubServerDir.constData());
|
||||
return tr("Cannot create socket '%1': %2").arg(stubServer, m_stubServer.errorString());
|
||||
@@ -190,11 +189,9 @@ void ConsoleProcess::readStubOutput()
|
||||
QByteArray out = m_stubSocket->readLine();
|
||||
out.chop(1); // \n
|
||||
if (out.startsWith("err:chdir ")) {
|
||||
emit processError(tr("Cannot change to working directory '%1': %2")
|
||||
.arg(workingDirectory(), errorMsg(out.mid(10).toInt())));
|
||||
emit processError(msgCannotChangeToWorkDir(workingDirectory(), errorMsg(out.mid(10).toInt())));
|
||||
} else if (out.startsWith("err:exec ")) {
|
||||
emit processError(tr("Cannot execute '%1': %2")
|
||||
.arg(m_executable, errorMsg(out.mid(9).toInt())));
|
||||
emit processError(msgCannotExecute(m_executable, errorMsg(out.mid(9).toInt())));
|
||||
} else if (out.startsWith("pid ")) {
|
||||
// Will not need it any more
|
||||
delete m_tempFile;
|
||||
@@ -213,7 +210,7 @@ void ConsoleProcess::readStubOutput()
|
||||
m_appPid = 0;
|
||||
emit processStopped();
|
||||
} else {
|
||||
emit processError(tr("Unexpected output from helper program."));
|
||||
emit processError(msgUnexpectedOutput());
|
||||
m_process.terminate();
|
||||
break;
|
||||
}
|
||||
@@ -250,7 +247,7 @@ QString ConsoleProcess::defaultTerminalEmulator()
|
||||
|
||||
QString ConsoleProcess::terminalEmulator(const QSettings *settings)
|
||||
{
|
||||
QString dflt = defaultTerminalEmulator() + QLatin1String(" -e");
|
||||
const QString dflt = defaultTerminalEmulator() + QLatin1String(" -e");
|
||||
if (!settings)
|
||||
return dflt;
|
||||
return settings->value(QLatin1String("General/TerminalEmulator"), dflt).toString();
|
||||
|
||||
@@ -42,18 +42,17 @@
|
||||
|
||||
using namespace Core::Utils;
|
||||
|
||||
ConsoleProcess::ConsoleProcess(QObject *parent)
|
||||
: QObject(parent)
|
||||
ConsoleProcess::ConsoleProcess(QObject *parent) :
|
||||
QObject(parent),
|
||||
m_mode(Run),
|
||||
m_appPid(0),
|
||||
m_pid(0),
|
||||
m_hInferior(NULL),
|
||||
m_tempFile(0),
|
||||
m_stubSocket(0),
|
||||
processFinishedNotifier(0),
|
||||
inferiorFinishedNotifier(0)
|
||||
{
|
||||
m_debug = false;
|
||||
m_appPid = 0;
|
||||
m_pid = 0;
|
||||
m_hInferior = NULL;
|
||||
m_tempFile = 0;
|
||||
m_stubSocket = 0;
|
||||
processFinishedNotifier = 0;
|
||||
inferiorFinishedNotifier = 0;
|
||||
|
||||
connect(&m_stubServer, SIGNAL(newConnection()), SLOT(stubConnectionAvailable()));
|
||||
}
|
||||
|
||||
@@ -67,9 +66,9 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
|
||||
if (isRunning())
|
||||
return false;
|
||||
|
||||
QString err = stubServerListen();
|
||||
const QString err = stubServerListen();
|
||||
if (!err.isEmpty()) {
|
||||
emit processError(tr("Cannot set up communication channel: %1").arg(err));
|
||||
emit processError(msgCommChannelFailed(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,7 +76,7 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
|
||||
m_tempFile = new QTemporaryFile();
|
||||
if (!m_tempFile->open()) {
|
||||
stubServerShutdown();
|
||||
emit processError(tr("Cannot create temporary file: %1").arg(m_tempFile->errorString()));
|
||||
emit processError(msgCannotCreateTempFile(m_tempFile->errorString()));
|
||||
delete m_tempFile;
|
||||
m_tempFile = 0;
|
||||
return false;
|
||||
@@ -102,15 +101,15 @@ bool ConsoleProcess::start(const QString &program, const QStringList &args)
|
||||
workDir.append('\\');
|
||||
|
||||
QStringList stubArgs;
|
||||
stubArgs << (m_debug ? "debug" : "exec")
|
||||
stubArgs << modeOption(m_mode)
|
||||
<< m_stubServer.fullServerName()
|
||||
<< workDir
|
||||
<< (m_tempFile ? m_tempFile->fileName() : 0)
|
||||
<< createWinCommandline(program, args)
|
||||
<< tr("Press <RETURN> to close this window...");
|
||||
<< msgPromptToClose();
|
||||
|
||||
QString cmdLine = createWinCommandline(
|
||||
QCoreApplication::applicationDirPath() + "/qtcreator_process_stub.exe", stubArgs);
|
||||
const QString cmdLine = createWinCommandline(
|
||||
QCoreApplication::applicationDirPath() + QLatin1String("/qtcreator_process_stub.exe"), stubArgs);
|
||||
|
||||
bool success = CreateProcessW(0, (WCHAR*)cmdLine.utf16(),
|
||||
0, 0, FALSE, CREATE_NEW_CONSOLE,
|
||||
@@ -180,13 +179,11 @@ void ConsoleProcess::readStubOutput()
|
||||
QByteArray out = m_stubSocket->readLine();
|
||||
out.chop(2); // \r\n
|
||||
if (out.startsWith("err:chdir ")) {
|
||||
emit processError(tr("Cannot change to working directory '%1': %2")
|
||||
.arg(workingDirectory(), winErrorMessage(out.mid(10).toInt())));
|
||||
emit processError(msgCannotChangeToWorkDir(workingDirectory(), winErrorMessage(out.mid(10).toInt())));
|
||||
} else if (out.startsWith("err:exec ")) {
|
||||
emit processError(tr("Cannot execute '%1': %2")
|
||||
.arg(m_executable, winErrorMessage(out.mid(9).toInt())));
|
||||
emit processError(msgCannotExecute(m_executable, winErrorMessage(out.mid(9).toInt())));
|
||||
} else if (out.startsWith("pid ")) {
|
||||
// Will not need it any more
|
||||
// Wil not need it any more
|
||||
delete m_tempFile;
|
||||
m_tempFile = 0;
|
||||
|
||||
@@ -204,7 +201,7 @@ void ConsoleProcess::readStubOutput()
|
||||
connect(inferiorFinishedNotifier, SIGNAL(activated(HANDLE)), SLOT(inferiorExited()));
|
||||
emit processStarted();
|
||||
} else {
|
||||
emit processError(tr("Unexpected output from helper program."));
|
||||
emit processError(msgUnexpectedOutput());
|
||||
TerminateProcess(m_pid->hProcess, (unsigned)-1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
IDE_BUILD_TREE = $$OUT_PWD/../../..
|
||||
include(../../../qtcreator.pri)
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = qtcreator_process_stub
|
||||
macx {
|
||||
DESTDIR = $$IDE_BUILD_TREE/bin/$${IDE_APP_TARGET}.app/Contents/Resources
|
||||
} else {
|
||||
DESTDIR = ../../../bin
|
||||
}
|
||||
DESTDIR = $$IDE_LIBEXEC_PATH
|
||||
|
||||
CONFIG += warn_on console use_c_linker
|
||||
CONFIG -= qt app_bundle
|
||||
@@ -24,5 +19,5 @@ unix {
|
||||
LIBS += -lshell32
|
||||
}
|
||||
|
||||
target.path = /bin
|
||||
target.path = /bin # FIXME: libexec, more or less
|
||||
INSTALLS += target
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
static FILE *qtcFd;
|
||||
static wchar_t *sleepMsg;
|
||||
|
||||
enum RunMode { Run, Debug, Suspend };
|
||||
|
||||
/* Print some "press enter" message, wait for that, exit. */
|
||||
static void doExit(int code)
|
||||
{
|
||||
@@ -112,6 +114,7 @@ int main()
|
||||
STARTUPINFOW si;
|
||||
PROCESS_INFORMATION pi;
|
||||
DEBUG_EVENT dbev;
|
||||
enum RunMode mode = Run;
|
||||
|
||||
argv = CommandLineToArgvW(GetCommandLine(), &argc);
|
||||
|
||||
@@ -158,8 +161,20 @@ int main()
|
||||
si.cb = sizeof(si);
|
||||
|
||||
creationFlags = CREATE_UNICODE_ENVIRONMENT;
|
||||
if (!wcscmp(argv[ArgAction], L"debug"))
|
||||
if (!wcscmp(argv[ArgAction], L"debug")) {
|
||||
mode = Debug;
|
||||
} else if (!wcscmp(argv[ArgAction], L"suspend")) {
|
||||
mode = Suspend;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case Debug:
|
||||
creationFlags |= DEBUG_ONLY_THIS_PROCESS;
|
||||
break;
|
||||
case Suspend:
|
||||
creationFlags |= CREATE_SUSPENDED;
|
||||
break;
|
||||
}
|
||||
if (!CreateProcessW(0, argv[ArgCmdLine], 0, 0, FALSE, creationFlags, env, 0, &si, &pi)) {
|
||||
/* Only expected error: no such file or direcotry, i.e. executable not found */
|
||||
sendMsg("err:exec %d\n", GetLastError());
|
||||
@@ -172,7 +187,7 @@ int main()
|
||||
So instead we start a debugged process, eat all the initial
|
||||
debug events, suspend the process and detach from it. If gdb
|
||||
tries to attach *now*, everything goes smoothly. Yay. */
|
||||
if (creationFlags & DEBUG_ONLY_THIS_PROCESS) {
|
||||
if (mode == Debug) {
|
||||
do {
|
||||
if (!WaitForDebugEvent (&dbev, INFINITE))
|
||||
systemError("Cannot fetch debug event, error %d\n");
|
||||
|
||||
@@ -26,7 +26,8 @@ SOURCES += \
|
||||
savedaction.cpp \
|
||||
submiteditorwidget.cpp \
|
||||
synchronousprocess.cpp \
|
||||
submitfieldwidget.cpp
|
||||
submitfieldwidget.cpp \
|
||||
consoleprocess.cpp
|
||||
|
||||
win32 {
|
||||
SOURCES += abstractprocess_win.cpp \
|
||||
|
||||
@@ -153,7 +153,7 @@ using namespace Core::Internal;
|
||||
*/
|
||||
|
||||
ActionContainerPrivate::ActionContainerPrivate(int id)
|
||||
: m_data(CS_None), m_id(id)
|
||||
: m_data(0), m_id(id)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -168,16 +168,6 @@ bool ActionContainerPrivate::hasEmptyAction(EmptyAction ea) const
|
||||
return (m_data & EA_Mask) == ea;
|
||||
}
|
||||
|
||||
void ActionContainerPrivate::setState(ContainerState state)
|
||||
{
|
||||
m_data |= state;
|
||||
}
|
||||
|
||||
bool ActionContainerPrivate::hasState(ContainerState state) const
|
||||
{
|
||||
return (m_data & state);
|
||||
}
|
||||
|
||||
void ActionContainerPrivate::appendGroup(const QString &group)
|
||||
{
|
||||
int gid = UniqueIDManager::instance()->uniqueIdentifier(group);
|
||||
@@ -198,26 +188,14 @@ void ActionContainerPrivate::addAction(Command *action, const QString &group)
|
||||
return;
|
||||
|
||||
ActionManagerPrivate *am = ActionManagerPrivate::instance();
|
||||
Action *a = static_cast<Action *>(action);
|
||||
if (a->stateFlags() & CommandPrivate::CS_PreLocation) {
|
||||
QList<CommandLocation> locs = a->locations();
|
||||
for (int i=0; i<locs.size(); ++i) {
|
||||
if (ActionContainer *aci = am->actionContainer(locs.at(i).m_container)) {
|
||||
ActionContainerPrivate *ac = static_cast<ActionContainerPrivate *>(aci);
|
||||
ac->addAction(action, locs.at(i).m_position, false);
|
||||
}
|
||||
}
|
||||
a->setStateFlags(a->stateFlags() | CommandPrivate::CS_Initialized);
|
||||
} else {
|
||||
UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||
int grpid = idmanager->uniqueIdentifier(Constants::G_DEFAULT_TWO);
|
||||
if (!group.isEmpty())
|
||||
grpid = idmanager->uniqueIdentifier(group);
|
||||
if (!m_groups.contains(grpid) && !am->defaultGroups().contains(grpid))
|
||||
qWarning() << "*** addAction(): Unknown group: " << group;
|
||||
int pos = ((grpid << 16) | 0xFFFF);
|
||||
addAction(action, pos, true);
|
||||
}
|
||||
UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||
int grpid = idmanager->uniqueIdentifier(Constants::G_DEFAULT_TWO);
|
||||
if (!group.isEmpty())
|
||||
grpid = idmanager->uniqueIdentifier(group);
|
||||
if (!m_groups.contains(grpid) && !am->defaultGroups().contains(grpid))
|
||||
qWarning() << "*** addAction(): Unknown group: " << group;
|
||||
int pos = ((grpid << 16) | 0xFFFF);
|
||||
addAction(action, pos, true);
|
||||
}
|
||||
|
||||
void ActionContainerPrivate::addMenu(ActionContainer *menu, const QString &group)
|
||||
@@ -227,24 +205,14 @@ void ActionContainerPrivate::addMenu(ActionContainer *menu, const QString &group
|
||||
return;
|
||||
|
||||
ActionManagerPrivate *am = ActionManagerPrivate::instance();
|
||||
MenuActionContainer *mc = static_cast<MenuActionContainer *>(menu);
|
||||
if (mc->hasState(ActionContainerPrivate::CS_PreLocation)) {
|
||||
CommandLocation loc = mc->location();
|
||||
if (ActionContainer *aci = am->actionContainer(loc.m_container)) {
|
||||
ActionContainerPrivate *ac = static_cast<ActionContainerPrivate *>(aci);
|
||||
ac->addMenu(menu, loc.m_position, false);
|
||||
}
|
||||
mc->setState(ActionContainerPrivate::CS_Initialized);
|
||||
} else {
|
||||
UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||
int grpid = idmanager->uniqueIdentifier(Constants::G_DEFAULT_TWO);
|
||||
if (!group.isEmpty())
|
||||
grpid = idmanager->uniqueIdentifier(group);
|
||||
if (!m_groups.contains(grpid) && !am->defaultGroups().contains(grpid))
|
||||
qWarning() << "*** addMenu(): Unknown group: " << group;
|
||||
int pos = ((grpid << 16) | 0xFFFF);
|
||||
addMenu(menu, pos, true);
|
||||
}
|
||||
UniqueIDManager *idmanager = UniqueIDManager::instance();
|
||||
int grpid = idmanager->uniqueIdentifier(Constants::G_DEFAULT_TWO);
|
||||
if (!group.isEmpty())
|
||||
grpid = idmanager->uniqueIdentifier(group);
|
||||
if (!m_groups.contains(grpid) && !am->defaultGroups().contains(grpid))
|
||||
qWarning() << "*** addMenu(): Unknown group: " << group;
|
||||
int pos = ((grpid << 16) | 0xFFFF);
|
||||
addMenu(menu, pos, true);
|
||||
}
|
||||
|
||||
int ActionContainerPrivate::id() const
|
||||
@@ -264,14 +232,7 @@ QMenuBar *ActionContainerPrivate::menuBar() const
|
||||
|
||||
bool ActionContainerPrivate::canAddAction(Command *action) const
|
||||
{
|
||||
if (action->type() != Command::CT_OverridableAction)
|
||||
return false;
|
||||
|
||||
CommandPrivate *cmd = static_cast<CommandPrivate *>(action);
|
||||
if (cmd->stateFlags() & CommandPrivate::CS_Initialized)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return (action->action() != 0);
|
||||
}
|
||||
|
||||
void ActionContainerPrivate::addAction(Command *action, int pos, bool setpos)
|
||||
@@ -444,9 +405,6 @@ bool MenuActionContainer::update()
|
||||
|
||||
bool MenuActionContainer::canBeAddedToMenu() const
|
||||
{
|
||||
if (hasState(ActionContainerPrivate::CS_Initialized))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,22 +41,12 @@ namespace Internal {
|
||||
class ActionContainerPrivate : public Core::ActionContainer
|
||||
{
|
||||
public:
|
||||
enum ContainerState {
|
||||
CS_None = 0x000000,
|
||||
CS_Initialized = 0x010000,
|
||||
CS_PreLocation = 0x020000,
|
||||
CS_UserDefined = 0x040000
|
||||
};
|
||||
|
||||
ActionContainerPrivate(int id);
|
||||
virtual ~ActionContainerPrivate() {}
|
||||
|
||||
void setEmptyAction(EmptyAction ea);
|
||||
bool hasEmptyAction(EmptyAction ea) const;
|
||||
|
||||
void setState(ContainerState state);
|
||||
bool hasState(ContainerState state) const;
|
||||
|
||||
QAction *insertLocation(const QString &group) const;
|
||||
void appendGroup(const QString &group);
|
||||
void addAction(Command *action, const QString &group = QString());
|
||||
|
||||
@@ -335,13 +335,12 @@ Command *ActionManagerPrivate::registerOverridableAction(QAction *action, const
|
||||
OverrideableAction *a = 0;
|
||||
const int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
|
||||
if (CommandPrivate *c = m_idCmdMap.value(uid, 0)) {
|
||||
if (c->type() != Command::CT_OverridableAction) {
|
||||
a = qobject_cast<OverrideableAction *>(c);
|
||||
if (!a) {
|
||||
qWarning() << "registerAction: id" << id << "is registered with a different command type.";
|
||||
return c;
|
||||
}
|
||||
a = static_cast<OverrideableAction *>(c);
|
||||
}
|
||||
if (!a) {
|
||||
} else {
|
||||
a = new OverrideableAction(uid);
|
||||
m_idCmdMap.insert(uid, a);
|
||||
}
|
||||
@@ -381,11 +380,11 @@ Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const QStri
|
||||
Shortcut *sc = 0;
|
||||
int uid = UniqueIDManager::instance()->uniqueIdentifier(id);
|
||||
if (CommandPrivate *c = m_idCmdMap.value(uid, 0)) {
|
||||
if (c->type() != Command::CT_Shortcut) {
|
||||
sc = qobject_cast<Shortcut *>(c);
|
||||
if (!sc) {
|
||||
qWarning() << "registerShortcut: id" << id << "is registered with a different command type.";
|
||||
return c;
|
||||
}
|
||||
sc = static_cast<Shortcut *>(c);
|
||||
} else {
|
||||
sc = new Shortcut(uid);
|
||||
m_idCmdMap.insert(uid, sc);
|
||||
|
||||
@@ -38,80 +38,165 @@
|
||||
\mainclass
|
||||
|
||||
\brief The class Command represents an action like a menu item, tool button, or shortcut.
|
||||
You don't create Command objects directly, instead use \l{ActionManager::registerAction()}
|
||||
to register an action and retrieve a Command. The Command object represents the user visible
|
||||
action and its properties. If multiple actions are registered with the same ID (but
|
||||
different contexts) the returned Command is the shared one between these actions.
|
||||
|
||||
*/
|
||||
A Command has two basic properties: A default shortcut and a default text. The default
|
||||
shortcut is a key sequence that the user can use to trigger the active action that
|
||||
the Command represents. The default text is e.g. used for representing the Command
|
||||
in the keyboard shortcut preference pane. If the default text is empty, the text
|
||||
of the visible action is used.
|
||||
|
||||
/*!
|
||||
\enum Command::CommandType
|
||||
The user visible action is updated to represent the state of the active action (if any).
|
||||
For performance reasons only the enabled and visible state are considered by default though.
|
||||
You can tell a Command to also update the actions icon and text by setting the
|
||||
corresponding \l{Command::CommandAttribute}{attribute}.
|
||||
|
||||
If there is no active action, the default behavior of the visible action is to be disabled.
|
||||
You can change that behavior to make the visible action hide instead via the Command's
|
||||
\l{Command::CommandAttribute}{attributes}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum Command::CommandAttribute
|
||||
Defines how the user visible action is updated when the active action changes.
|
||||
The default is to update the enabled and visible state, and to disable the
|
||||
user visible action when there is no active action.
|
||||
\omitvalue CA_Mask
|
||||
\value CA_UpdateText
|
||||
Also update the actions text.
|
||||
\value CA_UpdateIcon
|
||||
Also update the actions icon.
|
||||
\value CA_Hide
|
||||
When there is no active action, hide the user "visible" action, instead of just
|
||||
disabling it.
|
||||
\value CA_NonConfigureable
|
||||
Flag to indicate that the keyboard shortcut of this Command should not be
|
||||
configurable by the user.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual void Command::setDefaultKeySequence(const QKeySequence &key)
|
||||
\fn void Command::setDefaultKeySequence(const QKeySequence &key)
|
||||
Set the default keyboard shortcut that can be used to activate this command to \a key.
|
||||
This is used if the user didn't customize the shortcut, or resets the shortcut
|
||||
to the default one.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual int Command::id() const
|
||||
\fn void Command::defaultKeySequence() const
|
||||
Returns the default keyboard shortcut that can be used to activate this command.
|
||||
\sa setDefaultKeySequence()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual CommandType Command::type() const
|
||||
\fn void Command::keySequenceChanged()
|
||||
Sent when the keyboard shortcut assigned to this Command changes, e.g.
|
||||
when the user sets it in the keyboard shortcut settings dialog.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual QAction *Command::action() const
|
||||
\fn QKeySequence Command::keySequence() const
|
||||
Returns the current keyboard shortcut assigned to this Command.
|
||||
\sa defaultKeySequence()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual QShortcut *Command::shortcut() const
|
||||
\fn void Command::setKeySequence(const QKeySequence &key)
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual void Command::setAttribute(CommandAttribute attr)
|
||||
\fn void Command::setDefaultText(const QString &text)
|
||||
Set the \a text that is used to represent the Command in the
|
||||
keyboard shortcut settings dialog. If you don't set this,
|
||||
the current text from the user visible action is taken (which
|
||||
is ok in many cases).
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual void Command::removeAttribute(CommandAttribute attr)
|
||||
\fn QString Command::defaultText() const
|
||||
Returns the text that is used to present this Command to the user.
|
||||
\sa setDefaultText()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual bool Command::hasAttribute(CommandAttribute attr) const
|
||||
\fn int Command::id() const
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual bool Command::isActive() const
|
||||
\fn QString Command::stringWithAppendedShortcut(const QString &string) const
|
||||
Returns the \a string with an appended representation of the keyboard shortcut
|
||||
that is currently assigned to this Command.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn virtual Command::~Command()
|
||||
\fn QAction *Command::action() const
|
||||
Returns the user visible action for this Command.
|
||||
If the Command represents a shortcut, it returns null.
|
||||
Use this action to put it on e.g. tool buttons. The action
|
||||
automatically forwards trigger and toggle signals to the
|
||||
action that is currently active for this Command.
|
||||
It also shows the current keyboard shortcut in its
|
||||
tool tip (in addition to the tool tip of the active action)
|
||||
and gets disabled/hidden when there is
|
||||
no active action for the current context.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QShortcut *Command::shortcut() const
|
||||
Returns the shortcut for this Command.
|
||||
If the Command represents an action, it returns null.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void Command::setAttribute(CommandAttribute attribute)
|
||||
Add the \a attribute to the attributes of this Command.
|
||||
\sa CommandAttribute
|
||||
\sa removeAttribute()
|
||||
\sa hasAttribute()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void Command::removeAttribute(CommandAttribute attribute)
|
||||
Remove the \a attribute from the attributes of this Command.
|
||||
\sa CommandAttribute
|
||||
\sa setAttribute()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool Command::hasAttribute(CommandAttribute attribute) const
|
||||
Returns if the Command has the \a attribute set.
|
||||
\sa CommandAttribute
|
||||
\sa removeAttribute()
|
||||
\sa setAttribute()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn bool Command::isActive() const
|
||||
Returns if the Command has an active action/shortcut for the current
|
||||
context.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn Command::~Command()
|
||||
\internal
|
||||
*/
|
||||
|
||||
using namespace Core::Internal;
|
||||
|
||||
/*!
|
||||
\class CommandPrivate
|
||||
\inheaderfile command_p.h
|
||||
\internal
|
||||
*/
|
||||
|
||||
CommandPrivate::CommandPrivate(CommandType type, int id)
|
||||
: m_type(type), m_id(id)
|
||||
CommandPrivate::CommandPrivate(int id)
|
||||
: m_attributes(0), m_id(id)
|
||||
{
|
||||
}
|
||||
|
||||
void CommandPrivate::setStateFlags(int state)
|
||||
{
|
||||
m_type |= (state & CS_Mask);
|
||||
}
|
||||
|
||||
int CommandPrivate::stateFlags() const
|
||||
{
|
||||
return (m_type & CS_Mask);
|
||||
}
|
||||
|
||||
void CommandPrivate::setDefaultKeySequence(const QKeySequence &key)
|
||||
{
|
||||
m_defaultKey = key;
|
||||
@@ -137,11 +222,6 @@ int CommandPrivate::id() const
|
||||
return m_id;
|
||||
}
|
||||
|
||||
CommandPrivate::CommandType CommandPrivate::type() const
|
||||
{
|
||||
return (CommandType)(m_type & CT_Mask);
|
||||
}
|
||||
|
||||
QAction *CommandPrivate::action() const
|
||||
{
|
||||
return 0;
|
||||
@@ -154,17 +234,17 @@ QShortcut *CommandPrivate::shortcut() const
|
||||
|
||||
void CommandPrivate::setAttribute(CommandAttribute attr)
|
||||
{
|
||||
m_type |= attr;
|
||||
m_attributes |= attr;
|
||||
}
|
||||
|
||||
void CommandPrivate::removeAttribute(CommandAttribute attr)
|
||||
{
|
||||
m_type &= ~attr;
|
||||
m_attributes &= ~attr;
|
||||
}
|
||||
|
||||
bool CommandPrivate::hasAttribute(CommandAttribute attr) const
|
||||
{
|
||||
return (m_type & attr);
|
||||
return (m_attributes & attr);
|
||||
}
|
||||
|
||||
QString CommandPrivate::stringWithAppendedShortcut(const QString &str) const
|
||||
@@ -177,20 +257,15 @@ QString CommandPrivate::stringWithAppendedShortcut(const QString &str) const
|
||||
|
||||
/*!
|
||||
\class Shortcut
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
Shortcut::Shortcut(int id)
|
||||
: CommandPrivate(CT_Shortcut, id), m_shortcut(0)
|
||||
: CommandPrivate(id), m_shortcut(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
QString Shortcut::name() const
|
||||
{
|
||||
if (!m_shortcut)
|
||||
@@ -199,41 +274,26 @@ QString Shortcut::name() const
|
||||
return m_shortcut->whatsThis();
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void Shortcut::setShortcut(QShortcut *shortcut)
|
||||
{
|
||||
m_shortcut = shortcut;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
QShortcut *Shortcut::shortcut() const
|
||||
{
|
||||
return m_shortcut;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void Shortcut::setContext(const QList<int> &context)
|
||||
{
|
||||
m_context = context;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
QList<int> Shortcut::context() const
|
||||
{
|
||||
return m_context;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void Shortcut::setDefaultKeySequence(const QKeySequence &key)
|
||||
{
|
||||
setKeySequence(key);
|
||||
@@ -261,9 +321,6 @@ QString Shortcut::defaultText() const
|
||||
return m_defaultText;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
bool Shortcut::setCurrentContext(const QList<int> &context)
|
||||
{
|
||||
foreach (int ctxt, m_context) {
|
||||
@@ -276,9 +333,6 @@ bool Shortcut::setCurrentContext(const QList<int> &context)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
bool Shortcut::isActive() const
|
||||
{
|
||||
return m_shortcut->isEnabled();
|
||||
@@ -287,21 +341,15 @@ bool Shortcut::isActive() const
|
||||
// ---------- Action ------------
|
||||
|
||||
/*!
|
||||
\class Action
|
||||
\class Action
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
Action::Action(CommandType type, int id)
|
||||
: CommandPrivate(type, id), m_action(0)
|
||||
Action::Action(int id)
|
||||
: CommandPrivate(id), m_action(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
QString Action::name() const
|
||||
{
|
||||
if (!m_action)
|
||||
@@ -310,9 +358,6 @@ QString Action::name() const
|
||||
return m_action->text();
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void Action::setAction(QAction *action)
|
||||
{
|
||||
m_action = action;
|
||||
@@ -322,33 +367,21 @@ void Action::setAction(QAction *action)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
QAction *Action::action() const
|
||||
{
|
||||
return m_action;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void Action::setLocations(const QList<CommandLocation> &locations)
|
||||
{
|
||||
m_locations = locations;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
QList<CommandLocation> Action::locations() const
|
||||
{
|
||||
return m_locations;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void Action::setDefaultKeySequence(const QKeySequence &key)
|
||||
{
|
||||
setKeySequence(key);
|
||||
@@ -379,28 +412,20 @@ QKeySequence Action::keySequence() const
|
||||
|
||||
/*!
|
||||
\class OverrideableAction
|
||||
\internal
|
||||
*/
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
OverrideableAction::OverrideableAction(int id)
|
||||
: Action(CT_OverridableAction, id), m_currentAction(0), m_active(false),
|
||||
: Action(id), m_currentAction(0), m_active(false),
|
||||
m_contextInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void OverrideableAction::setAction(QAction *action)
|
||||
{
|
||||
Action::setAction(action);
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
bool OverrideableAction::setCurrentContext(const QList<int> &context)
|
||||
{
|
||||
m_context = context;
|
||||
@@ -440,9 +465,6 @@ bool OverrideableAction::setCurrentContext(const QList<int> &context)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void OverrideableAction::addOverrideAction(QAction *action, const QList<int> &context)
|
||||
{
|
||||
if (context.isEmpty()) {
|
||||
@@ -457,9 +479,6 @@ void OverrideableAction::addOverrideAction(QAction *action, const QList<int> &co
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
void OverrideableAction::actionChanged()
|
||||
{
|
||||
if (hasAttribute(CA_UpdateIcon)) {
|
||||
@@ -482,9 +501,6 @@ void OverrideableAction::actionChanged()
|
||||
m_action->setVisible(m_currentAction->isVisible());
|
||||
}
|
||||
|
||||
/*!
|
||||
...
|
||||
*/
|
||||
bool OverrideableAction::isActive() const
|
||||
{
|
||||
return m_active;
|
||||
|
||||
@@ -42,12 +42,6 @@ class CORE_EXPORT Command : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum CommandType {
|
||||
CT_Shortcut = 0x0001,
|
||||
CT_OverridableAction = 0x0002,
|
||||
CT_Mask = 0x00FF
|
||||
};
|
||||
|
||||
enum CommandAttribute {
|
||||
CA_Hide = 0x0100,
|
||||
CA_UpdateText = 0x0200,
|
||||
@@ -57,14 +51,12 @@ public:
|
||||
};
|
||||
|
||||
virtual void setDefaultKeySequence(const QKeySequence &key) = 0;
|
||||
virtual void setKeySequence(const QKeySequence &key) = 0;
|
||||
virtual QKeySequence defaultKeySequence() const = 0;
|
||||
virtual QKeySequence keySequence() const = 0;
|
||||
virtual void setDefaultText(const QString &text) = 0;
|
||||
virtual QString defaultText() const = 0;
|
||||
|
||||
virtual int id() const = 0;
|
||||
virtual CommandType type() const = 0;
|
||||
|
||||
virtual QAction *action() const = 0;
|
||||
virtual QShortcut *shortcut() const = 0;
|
||||
@@ -77,6 +69,8 @@ public:
|
||||
|
||||
virtual ~Command() {}
|
||||
|
||||
virtual void setKeySequence(const QKeySequence &key) = 0;
|
||||
|
||||
virtual QString stringWithAppendedShortcut(const QString &str) const = 0;
|
||||
|
||||
signals:
|
||||
|
||||
@@ -45,19 +45,9 @@ class CommandPrivate : public Core::Command
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum CommandState {
|
||||
CS_PreLocation = 0x020000,
|
||||
CS_LocationChanged = 0x040000,
|
||||
CS_Initialized = 0x080000,
|
||||
CS_Mask = 0xFF0000
|
||||
};
|
||||
|
||||
CommandPrivate(CommandType type, int id);
|
||||
CommandPrivate(int id);
|
||||
virtual ~CommandPrivate() {}
|
||||
|
||||
void setStateFlags(int state);
|
||||
int stateFlags() const;
|
||||
|
||||
virtual QString name() const = 0;
|
||||
|
||||
void setDefaultKeySequence(const QKeySequence &key);
|
||||
@@ -67,7 +57,6 @@ public:
|
||||
QString defaultText() const;
|
||||
|
||||
int id() const;
|
||||
CommandType type() const;
|
||||
|
||||
QAction *action() const;
|
||||
QShortcut *shortcut() const;
|
||||
@@ -82,7 +71,7 @@ public:
|
||||
|
||||
protected:
|
||||
QString m_category;
|
||||
int m_type;
|
||||
int m_attributes;
|
||||
int m_id;
|
||||
QKeySequence m_defaultKey;
|
||||
QString m_defaultText;
|
||||
@@ -121,7 +110,7 @@ class Action : public CommandPrivate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Action(CommandType type, int id);
|
||||
Action(int id);
|
||||
|
||||
QString name() const;
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
|
||||
#include <coreplugin/ifile.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtGui/QPushButton>
|
||||
#include <QtGui/QTreeWidget>
|
||||
#include <QtGui/QHeaderView>
|
||||
@@ -69,7 +71,7 @@ SaveItemsDialog::SaveItemsDialog(QWidget *parent,
|
||||
visibleName = info.fileName();
|
||||
}
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.treeWidget, QStringList()
|
||||
<< visibleName << directory);
|
||||
<< visibleName << QDir::toNativeSeparators(directory));
|
||||
item->setData(0, Qt::UserRole, qVariantFromValue(file));
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ void CppHighlighter::highlightBlock(const QString &text)
|
||||
braceDepth = previousState >> 8;
|
||||
}
|
||||
|
||||
|
||||
SimpleLexer tokenize;
|
||||
tokenize.setQtMocRunEnabled(false);
|
||||
|
||||
@@ -210,6 +211,28 @@ void CppHighlighter::highlightBlock(const QString &text)
|
||||
|
||||
TextEditDocumentLayout::setParentheses(currentBlock(), parentheses);
|
||||
|
||||
|
||||
// optimization: if only the brace depth changes, we adjust subsequent blocks
|
||||
// to have QSyntaxHighlighter stop the rehighlighting
|
||||
int currentState = currentBlockState();
|
||||
if (currentState != -1) {
|
||||
int oldState = currentState & 0xff;
|
||||
int oldBraceDepth = currentState >> 8;
|
||||
if (oldState == tokenize.state() && oldBraceDepth != braceDepth) {
|
||||
int delta = braceDepth - oldBraceDepth;
|
||||
QTextBlock block = currentBlock().next();
|
||||
while (block.isValid()) {
|
||||
currentState = block.userState();
|
||||
if (currentState != -1) {
|
||||
oldState = currentState & 0xff;
|
||||
oldBraceDepth = currentState >> 8;
|
||||
block.setUserState(qMax(0, (oldBraceDepth + delta) << 8 ) | oldState);
|
||||
}
|
||||
block = block.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentBlockState((braceDepth << 8) | tokenize.state());
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +392,7 @@ CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent, const QSharedPointer<Cdb
|
||||
IDebuggerEngine(parent),
|
||||
m_d(new CdbDebugEnginePrivate(parent, options, this))
|
||||
{
|
||||
// m_d->m_consoleStubProc.setDebug(true);
|
||||
m_d->m_consoleStubProc.setMode(Core::Utils::ConsoleProcess::Suspend);
|
||||
connect(&m_d->m_consoleStubProc, SIGNAL(processError(QString)), this, SLOT(slotConsoleStubError(QString)));
|
||||
connect(&m_d->m_consoleStubProc, SIGNAL(processStarted()), this, SLOT(slotConsoleStubStarted()));
|
||||
connect(&m_d->m_consoleStubProc, SIGNAL(wrapperStopped()), this, SLOT(slotConsoleStubTerminated()));
|
||||
@@ -469,10 +469,12 @@ bool CdbDebugEngine::startDebugger()
|
||||
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
|
||||
QString errorMessage;
|
||||
bool rc = false;
|
||||
bool needWatchTimer = false;
|
||||
m_d->clearForRun();
|
||||
switch (mode) {
|
||||
case AttachExternal:
|
||||
rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage);
|
||||
needWatchTimer = true;
|
||||
break;
|
||||
case StartInternal:
|
||||
case StartExternal:
|
||||
@@ -484,7 +486,9 @@ bool CdbDebugEngine::startDebugger()
|
||||
rc = m_d->m_consoleStubProc.start(m_d->m_debuggerManager->m_executable, m_d->m_debuggerManager->m_processArgs);
|
||||
if (!rc)
|
||||
errorMessage = tr("The console stub process was unable to start '%1'.").arg(m_d->m_debuggerManager->m_executable);
|
||||
// continues in slotConsoleStubStarted()...
|
||||
} else {
|
||||
needWatchTimer = true;
|
||||
rc = startDebuggerWithExecutable(mode, &errorMessage);
|
||||
}
|
||||
break;
|
||||
@@ -494,7 +498,8 @@ bool CdbDebugEngine::startDebugger()
|
||||
}
|
||||
if (rc) {
|
||||
m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
|
||||
startWatchTimer();
|
||||
if (needWatchTimer)
|
||||
startWatchTimer();
|
||||
} else {
|
||||
qWarning("%s\n", qPrintable(errorMessage));
|
||||
}
|
||||
@@ -503,12 +508,12 @@ bool CdbDebugEngine::startDebugger()
|
||||
|
||||
bool CdbDebugEngine::startAttachDebugger(qint64 pid, QString *errorMessage)
|
||||
{
|
||||
// Need to aatrach invasively, otherwise, no notification signals
|
||||
// Need to attrach invasively, otherwise, no notification signals
|
||||
// for for CreateProcess/ExitProcess occur.
|
||||
const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid,
|
||||
DEBUG_ATTACH_INVASIVE_RESUME_PROCESS);
|
||||
const ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS;
|
||||
const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid, flags);
|
||||
if (debugCDB)
|
||||
qDebug() << "Attaching to " << pid << " returns " << hr;
|
||||
qDebug() << "Attaching to " << pid << " returns " << hr << executionStatusString(m_d->m_cif.debugControl);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage = tr("AttachProcess failed for pid %1: %2").arg(pid).arg(msgDebugEngineComResult(hr));
|
||||
return false;
|
||||
@@ -560,7 +565,6 @@ bool CdbDebugEngine::startDebuggerWithExecutable(DebuggerStartMode sm, QString *
|
||||
m_d->m_mode = sm;
|
||||
}
|
||||
m_d->m_debuggerManagerAccess->notifyInferiorRunning();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1318,7 +1322,9 @@ void CdbDebugEngine::slotConsoleStubStarted()
|
||||
QString errorMessage;
|
||||
if (startAttachDebugger(appPid, &errorMessage)) {
|
||||
m_d->m_debuggerManager->m_attachedPID = appPid;
|
||||
startWatchTimer();
|
||||
m_d->m_debuggerManagerAccess->notifyInferiorPidChanged(appPid);
|
||||
m_d->m_debuggerManagerAccess->notifyInferiorRunning();
|
||||
} else {
|
||||
QMessageBox::critical(m_d->m_debuggerManager->mainWindow(), tr("Debugger Error"), errorMessage);
|
||||
}
|
||||
@@ -1343,7 +1349,8 @@ void CdbDebugEnginePrivate::notifyCrashed()
|
||||
void CdbDebugEnginePrivate::handleDebugEvent()
|
||||
{
|
||||
if (debugCDB)
|
||||
qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
|
||||
qDebug() << Q_FUNC_INFO << '\n' << m_hDebuggeeProcess << m_breakEventMode
|
||||
<< executionStatusString(m_cif.debugControl);
|
||||
|
||||
// restore mode and do special handling
|
||||
const HandleBreakEventMode mode = m_breakEventMode;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "breakhandler.h"
|
||||
#include "cdbstacktracecontext.h"
|
||||
|
||||
enum { cppExceptionCode = 0xe06d7363 };
|
||||
enum { cppExceptionCode = 0xe06d7363, startupCompleteTrap = 0x406d1388 };
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTextStream>
|
||||
@@ -245,6 +245,9 @@ void formatException(const EXCEPTION_RECORD64 *e, QTextStream &str)
|
||||
case cppExceptionCode:
|
||||
str << "C++ exception";
|
||||
break;
|
||||
case startupCompleteTrap:
|
||||
str << "Startup complete";
|
||||
break;
|
||||
case EXCEPTION_ACCESS_VIOLATION: {
|
||||
const bool writeOperation = e->ExceptionInformation[0];
|
||||
str << (writeOperation ? "write" : "read")
|
||||
@@ -341,7 +344,7 @@ static bool isFatalException(LONG code)
|
||||
switch (code) {
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
case EXCEPTION_SINGLE_STEP:
|
||||
case 0x406d1388: // Mysterious exception at start of application
|
||||
case startupCompleteTrap: // Mysterious exception at start of application
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
@@ -362,7 +365,7 @@ STDMETHODIMP CdbDebugEventCallback::Exception(
|
||||
}
|
||||
const bool fatal = isFatalException(Exception->ExceptionCode);
|
||||
if (debugCDB)
|
||||
qDebug() << Q_FUNC_INFO << '\n' << fatal << msg;
|
||||
qDebug() << Q_FUNC_INFO << "\nex=" << Exception->ExceptionCode << " fatal=" << fatal << msg;
|
||||
m_pEngine->m_d->m_debuggerManagerAccess->showApplicationOutput(msg);
|
||||
if (fatal)
|
||||
m_pEngine->m_d->notifyCrashed();
|
||||
|
||||
@@ -352,7 +352,7 @@ bool CdbDumperHelper::ensureInitialized(QString *errorMessage)
|
||||
return false;
|
||||
case CallLoadNoQtApp:
|
||||
m_access->showDebuggerOutput(m_messagePrefix, QCoreApplication::translate("CdbDumperHelper", "The debuggee does not appear to be Qt application."));
|
||||
disable();
|
||||
m_state = Disabled; // No message here
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -367,7 +367,7 @@ bool CdbDumperHelper::ensureInitialized(QString *errorMessage)
|
||||
m_access->showDebuggerOutput(m_messagePrefix, m_helper.toString());
|
||||
m_state = Initialized;
|
||||
} else {
|
||||
disable();
|
||||
m_state = Disabled; // No message here
|
||||
*errorMessage = QCoreApplication::translate("CdbDumperHelper", "The custom dumper library could not be initialized: %1").arg(*errorMessage);
|
||||
m_access->showDebuggerOutput(m_messagePrefix, *errorMessage);
|
||||
m_access->showQtDumperLibraryWarning(*errorMessage);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <coreplugin/icore.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
const char * const CDB_SETTINGS_ID = QT_TRANSLATE_NOOP("Debugger::Internal::CdbOptionsPageWidget", "CDB");
|
||||
const char * const CDB_SETTINGS_ID = QT_TRANSLATE_NOOP("Debugger::Internal::CdbOptionsPageWidget", "Cdb");
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<string>These options take effect at the next start of Qt Creator.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>CDB</string>
|
||||
<string>Cdb</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
||||
@@ -77,7 +77,6 @@ SOURCES += \
|
||||
gdboptionspage.cpp
|
||||
|
||||
FORMS += attachexternaldialog.ui \
|
||||
attachremotedialog.ui \
|
||||
attachcoredialog.ui \
|
||||
breakbyfunction.ui \
|
||||
breakcondition.ui \
|
||||
@@ -85,6 +84,7 @@ FORMS += attachexternaldialog.ui \
|
||||
gdboptionspage.ui \
|
||||
commonoptionspage.ui \
|
||||
startexternaldialog.ui \
|
||||
startremotedialog.ui \
|
||||
|
||||
RESOURCES += debugger.qrc
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
|
||||
#include "ui_attachcoredialog.h"
|
||||
#include "ui_attachexternaldialog.h"
|
||||
#include "ui_attachremotedialog.h"
|
||||
#include "ui_startexternaldialog.h"
|
||||
#include "ui_startremotedialog.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include "dbgwinutils.h"
|
||||
@@ -302,37 +302,39 @@ void AttachExternalDialog::pidChanged(const QString &pid)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AttachRemoteDialog
|
||||
// StartRemoteDialog
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent)
|
||||
StartRemoteDialog::StartRemoteDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
m_ui(new Ui::AttachRemoteDialog)
|
||||
m_ui(new Ui::StartRemoteDialog)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
m_ui->serverStartScript->setExpectedKind(Core::Utils::PathChooser::File);
|
||||
m_ui->serverStartScript->setPromptDialogTitle(tr("Select Executable"));
|
||||
|
||||
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
AttachRemoteDialog::~AttachRemoteDialog()
|
||||
StartRemoteDialog::~StartRemoteDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void AttachRemoteDialog::setRemoteChannel(const QString &channel)
|
||||
void StartRemoteDialog::setRemoteChannel(const QString &channel)
|
||||
{
|
||||
m_ui->channelLineEdit->setText(channel);
|
||||
}
|
||||
|
||||
QString AttachRemoteDialog::remoteChannel() const
|
||||
QString StartRemoteDialog::remoteChannel() const
|
||||
{
|
||||
return m_ui->channelLineEdit->text();
|
||||
}
|
||||
|
||||
void AttachRemoteDialog::setRemoteArchitectures(const QStringList &list)
|
||||
void StartRemoteDialog::setRemoteArchitectures(const QStringList &list)
|
||||
{
|
||||
m_ui->architectureComboBox->clear();
|
||||
if (!list.isEmpty()) {
|
||||
@@ -341,19 +343,28 @@ void AttachRemoteDialog::setRemoteArchitectures(const QStringList &list)
|
||||
}
|
||||
}
|
||||
|
||||
void AttachRemoteDialog::setRemoteArchitecture(const QString &arch)
|
||||
void StartRemoteDialog::setRemoteArchitecture(const QString &arch)
|
||||
{
|
||||
int index = m_ui->architectureComboBox->findText(arch);
|
||||
if (index != -1)
|
||||
m_ui->architectureComboBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
QString AttachRemoteDialog::remoteArchitecture() const
|
||||
QString StartRemoteDialog::remoteArchitecture() const
|
||||
{
|
||||
int index = m_ui->architectureComboBox->currentIndex();
|
||||
return m_ui->architectureComboBox->itemText(index);
|
||||
}
|
||||
|
||||
void StartRemoteDialog::setServerStartScript(const QString &scriptName)
|
||||
{
|
||||
m_ui->serverStartScript->setPath(scriptName);
|
||||
}
|
||||
|
||||
QString StartRemoteDialog::serverStartScript() const
|
||||
{
|
||||
return m_ui->serverStartScript->path();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
@@ -40,8 +40,8 @@ class QPushButton;
|
||||
namespace Ui {
|
||||
class AttachCoreDialog;
|
||||
class AttachExternalDialog;
|
||||
class AttachRemoteDialog;
|
||||
class StartExternalDialog;
|
||||
class StartRemoteDialog;
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
@@ -101,22 +101,24 @@ private:
|
||||
ProcessListFilterModel *m_model;
|
||||
};
|
||||
|
||||
class AttachRemoteDialog : public QDialog
|
||||
class StartRemoteDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttachRemoteDialog(QWidget *parent);
|
||||
~AttachRemoteDialog();
|
||||
explicit StartRemoteDialog(QWidget *parent);
|
||||
~StartRemoteDialog();
|
||||
|
||||
void setRemoteChannel(const QString &host);
|
||||
void setRemoteArchitecture(const QString &arch);
|
||||
void setRemoteArchitectures(const QStringList &arches);
|
||||
QString remoteChannel() const;
|
||||
QString remoteArchitecture() const;
|
||||
void setServerStartScript(const QString &scriptName);
|
||||
QString serverStartScript() const;
|
||||
|
||||
private:
|
||||
Ui::AttachRemoteDialog *m_ui;
|
||||
Ui::StartRemoteDialog *m_ui;
|
||||
};
|
||||
|
||||
class StartExternalDialog : public QDialog
|
||||
|
||||
@@ -929,21 +929,24 @@ void DebuggerManager::startNewDebugger(DebuggerRunControl *runControl)
|
||||
m_attachedPID = -1;
|
||||
break;
|
||||
}
|
||||
case AttachRemote: {
|
||||
AttachRemoteDialog dlg(mainWindow());
|
||||
case StartRemote: {
|
||||
StartRemoteDialog dlg(mainWindow());
|
||||
QStringList arches;
|
||||
arches.append(_("i386:x86-64:intel"));
|
||||
dlg.setRemoteArchitectures(arches);
|
||||
dlg.setRemoteChannel(configValue(_("LastRemoteChannel")).toString());
|
||||
dlg.setRemoteArchitecture(configValue(_("LastRemoteArchtecture")).toString());
|
||||
dlg.setServerStartScript(configValue(_("LastServerStartScript")).toString());
|
||||
if (dlg.exec() != QDialog::Accepted) {
|
||||
runControl->debuggingFinished();
|
||||
return;
|
||||
}
|
||||
setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel());
|
||||
setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture());
|
||||
setConfigValue(_("LastServerStartScript"), dlg.serverStartScript());
|
||||
m_remoteChannel = dlg.remoteChannel();
|
||||
m_remoteArchitecture = dlg.remoteArchitecture();
|
||||
m_serverStartScript = dlg.serverStartScript();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ enum DebuggerStartMode
|
||||
StartExternal, // Start binary found in file system
|
||||
AttachExternal, // Attach to running process
|
||||
AttachCore, // Attach to a core file
|
||||
AttachRemote // Attach to a remote process
|
||||
StartRemote // Start and attach to a remote process
|
||||
};
|
||||
|
||||
class IDebuggerEngine;
|
||||
@@ -359,8 +359,10 @@ public:
|
||||
QString m_dumperLib;
|
||||
int m_attachedPID;
|
||||
bool m_useTerminal;
|
||||
// for remote debugging
|
||||
QString m_remoteChannel;
|
||||
QString m_remoteArchitecture;
|
||||
QString m_serverStartScript;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
@@ -207,7 +207,7 @@ public slots:
|
||||
DebuggerOutputWindow::DebuggerOutputWindow(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setWindowTitle(tr("Gdb"));
|
||||
setWindowTitle(tr("Debugger"));
|
||||
|
||||
QSplitter *m_splitter = new QSplitter(Qt::Horizontal, this);
|
||||
// mixed input/output
|
||||
|
||||
@@ -480,10 +480,10 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
|
||||
m_attachCoreAction->setText(tr("Attach to Core..."));
|
||||
connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));
|
||||
|
||||
m_attachRemoteAction = new QAction(this);
|
||||
m_attachRemoteAction->setText(tr("Attach to Running Remote Application..."));
|
||||
connect(m_attachRemoteAction, SIGNAL(triggered()),
|
||||
this, SLOT(attachRemoteApplication()));
|
||||
m_startRemoteAction = new QAction(this);
|
||||
m_startRemoteAction->setText(tr("Start and Attach to Remote Application..."));
|
||||
connect(m_startRemoteAction, SIGNAL(triggered()),
|
||||
this, SLOT(startRemoteApplication()));
|
||||
|
||||
|
||||
Core::ActionContainer *mdebug =
|
||||
@@ -502,12 +502,9 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
|
||||
Constants::ATTACHCORE, globalcontext);
|
||||
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
|
||||
|
||||
#if 1
|
||||
// FIXME: not yet functional
|
||||
cmd = am->registerAction(m_attachRemoteAction,
|
||||
cmd = am->registerAction(m_startRemoteAction,
|
||||
Constants::ATTACHREMOTE, globalcontext);
|
||||
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
|
||||
#endif
|
||||
|
||||
cmd = am->registerAction(m_manager->m_continueAction,
|
||||
ProjectExplorer::Constants::DEBUG, QList<int>() << m_gdbRunningContext);
|
||||
@@ -1090,11 +1087,11 @@ void DebuggerPlugin::attachCore()
|
||||
runControl->start();
|
||||
}
|
||||
|
||||
void DebuggerPlugin::attachRemoteApplication()
|
||||
void DebuggerPlugin::startRemoteApplication()
|
||||
{
|
||||
QSharedPointer<RunConfiguration> rc = activeRunConfiguration();
|
||||
if (RunControl *runControl = m_debuggerRunner
|
||||
->run(rc, ProjectExplorer::Constants::DEBUGMODE, AttachRemote))
|
||||
->run(rc, ProjectExplorer::Constants::DEBUGMODE, StartRemote))
|
||||
runControl->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -98,9 +98,9 @@ private slots:
|
||||
void showSettingsDialog();
|
||||
|
||||
void startExternalApplication();
|
||||
void startRemoteApplication();
|
||||
void attachExternalApplication();
|
||||
void attachCore();
|
||||
void attachRemoteApplication();
|
||||
|
||||
private:
|
||||
void readSettings();
|
||||
@@ -122,9 +122,9 @@ private:
|
||||
QAction *m_toggleLockedAction;
|
||||
|
||||
QAction *m_startExternalAction;
|
||||
QAction *m_startRemoteAction;
|
||||
QAction *m_attachExternalAction;
|
||||
QAction *m_attachCoreAction;
|
||||
QAction *m_attachRemoteAction;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# This is a compile check for the dumpers only. Don't install the library!
|
||||
|
||||
include(../../qworkbenchlibrary.pri)
|
||||
|
||||
TEMPLATE = lib
|
||||
TARGET = DebuggingHelper
|
||||
CONFIG += shared
|
||||
DESTDIR = ../../../bin
|
||||
include(../../qworkbenchlibrary.pri)
|
||||
DESTDIR = $$IDE_LIBRARY_PATH # /tmp would be better in some respect ...
|
||||
|
||||
linux-* {
|
||||
CONFIG -= release
|
||||
|
||||
@@ -117,7 +117,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent)
|
||||
{
|
||||
q = parent;
|
||||
qq = parent->engineInterface();
|
||||
m_stubProc.setDebug(true);
|
||||
m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
|
||||
initializeVariables();
|
||||
initializeConnections();
|
||||
}
|
||||
@@ -131,22 +131,28 @@ GdbEngine::~GdbEngine()
|
||||
void GdbEngine::initializeConnections()
|
||||
{
|
||||
// Gdb Process interaction
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)), this,
|
||||
SLOT(gdbProcError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()), this,
|
||||
SLOT(readGdbStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()), this,
|
||||
SLOT(readGdbStandardError()));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)), q,
|
||||
SLOT(exitDebugger()));
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(gdbProcError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readGdbStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readGdbStandardError()));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
q, SLOT(exitDebugger()));
|
||||
|
||||
connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString)));
|
||||
connect(&m_stubProc, SIGNAL(processStarted()), SLOT(stubStarted()));
|
||||
connect(&m_stubProc, SIGNAL(wrapperStopped()), q, SLOT(exitDebugger()));
|
||||
connect(&m_stubProc, SIGNAL(processError(QString)),
|
||||
this, SLOT(stubError(QString)));
|
||||
connect(&m_stubProc, SIGNAL(processStarted()),
|
||||
this, SLOT(stubStarted()));
|
||||
connect(&m_stubProc, SIGNAL(wrapperStopped()),
|
||||
q, SLOT(exitDebugger()));
|
||||
|
||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(uploadProcError(QProcess::ProcessError)));
|
||||
|
||||
// Output
|
||||
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
|
||||
SLOT(readDebugeeOutput(QByteArray)));
|
||||
this, SLOT(readDebugeeOutput(QByteArray)));
|
||||
|
||||
connect(this, SIGNAL(gdbOutputAvailable(QString,QString)),
|
||||
q, SLOT(showDebuggerOutput(QString,QString)),
|
||||
@@ -225,6 +231,43 @@ void GdbEngine::gdbProcError(QProcess::ProcessError error)
|
||||
q->exitDebugger();
|
||||
}
|
||||
|
||||
void GdbEngine::uploadProcError(QProcess::ProcessError error)
|
||||
{
|
||||
QString msg;
|
||||
switch (error) {
|
||||
case QProcess::FailedToStart:
|
||||
msg = tr("The upload process failed to start. Either the "
|
||||
"invoked script '%1' is missing, or you may have insufficient "
|
||||
"permissions to invoke the program.")
|
||||
.arg(theDebuggerStringSetting(GdbLocation));
|
||||
break;
|
||||
case QProcess::Crashed:
|
||||
msg = tr("The upload process crashed some time after starting "
|
||||
"successfully.");
|
||||
break;
|
||||
case QProcess::Timedout:
|
||||
msg = tr("The last waitFor...() function timed out. "
|
||||
"The state of QProcess is unchanged, and you can try calling "
|
||||
"waitFor...() again.");
|
||||
break;
|
||||
case QProcess::WriteError:
|
||||
msg = tr("An error occurred when attempting to write "
|
||||
"to the upload process. For example, the process may not be running, "
|
||||
"or it may have closed its input channel.");
|
||||
break;
|
||||
case QProcess::ReadError:
|
||||
msg = tr("An error occurred when attempting to read from "
|
||||
"the upload process. For example, the process may not be running.");
|
||||
break;
|
||||
default:
|
||||
msg = tr("An unknown error in the upload process occurred. "
|
||||
"This is the default return value of error().");
|
||||
}
|
||||
|
||||
q->showStatusMessage(msg);
|
||||
QMessageBox::critical(q->mainWindow(), tr("Error"), msg);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dump(const char *first, const char *middle, const QString & to)
|
||||
{
|
||||
@@ -535,7 +578,7 @@ void GdbEngine::interruptInferior()
|
||||
return;
|
||||
}
|
||||
|
||||
if (q->startMode() == AttachRemote) {
|
||||
if (q->startMode() == StartRemote) {
|
||||
execCommand(_("-exec-interrupt"));
|
||||
return;
|
||||
}
|
||||
@@ -613,7 +656,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd)
|
||||
++currentToken();
|
||||
m_cookieForToken[currentToken()] = cmd;
|
||||
cmd.command = QString::number(currentToken()) + cmd.command;
|
||||
if (cmd.command.contains(__("%1")))
|
||||
if (cmd.flags & EmbedToken)
|
||||
cmd.command = cmd.command.arg(currentToken());
|
||||
|
||||
m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
|
||||
@@ -907,6 +950,7 @@ void GdbEngine::handleAqcuiredInferior()
|
||||
#endif
|
||||
if (theDebuggerBoolSetting(ListSourceFiles))
|
||||
reloadSourceFiles();
|
||||
|
||||
tryLoadDebuggingHelpers();
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
@@ -1313,7 +1357,7 @@ void GdbEngine::exitDebugger()
|
||||
qDebug() << "STATUS ON EXITDEBUGGER: " << q->status());
|
||||
interruptInferior();
|
||||
}
|
||||
if (q->startMode() == AttachExternal || q->startMode() == AttachRemote)
|
||||
if (q->startMode() == AttachExternal || q->startMode() == StartRemote)
|
||||
execCommand(_("detach"));
|
||||
else
|
||||
execCommand(_("kill"));
|
||||
@@ -1357,8 +1401,19 @@ bool GdbEngine::startDebugger()
|
||||
|
||||
if (q->startMode() == AttachCore || q->startMode() == AttachExternal) {
|
||||
// nothing to do
|
||||
} else if (q->startMode() == AttachRemote) {
|
||||
// nothing to do
|
||||
} else if (q->startMode() == StartRemote) {
|
||||
// Start the remote server
|
||||
if (q->m_serverStartScript.isEmpty()) {
|
||||
q->showStatusMessage(_("No server start script given. "
|
||||
"Assuming server runs already."));
|
||||
} else {
|
||||
if (!q->m_workingDir.isEmpty())
|
||||
m_uploadProc.setWorkingDirectory(q->m_workingDir);
|
||||
if (!q->m_environment.isEmpty())
|
||||
m_uploadProc.setEnvironment(q->m_environment);
|
||||
m_uploadProc.start(_("/bin/sh ") + q->m_serverStartScript);
|
||||
m_uploadProc.waitForStarted();
|
||||
}
|
||||
} else if (q->m_useTerminal) {
|
||||
m_stubProc.stop(); // We leave the console open, so recycle it now.
|
||||
|
||||
@@ -1495,7 +1550,7 @@ bool GdbEngine::startDebugger()
|
||||
execCommand(_("-file-exec-and-symbols ") + fileName);
|
||||
execCommand(_("target core ") + coreName, CB(handleTargetCore));
|
||||
qq->breakHandler()->removeAllBreakpoints();
|
||||
} else if (q->startMode() == AttachRemote) {
|
||||
} else if (q->startMode() == StartRemote) {
|
||||
execCommand(_("set architecture %1").arg(q->m_remoteArchitecture));
|
||||
qq->breakHandler()->setAllPending();
|
||||
//QFileInfo fi(q->m_executable);
|
||||
@@ -2795,7 +2850,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QString &type) const
|
||||
if (!theDebuggerBoolSetting(UseDebuggingHelpers))
|
||||
return false;
|
||||
|
||||
if (q->startMode() == AttachCore) {
|
||||
if (!startModeAllowsDumpers()) {
|
||||
// "call" is not possible in gdb when looking at core files
|
||||
return type == __("QString") || type.endsWith(__("::QString"))
|
||||
|| type == __("QStringList") || type.endsWith(__("::QStringList"));
|
||||
@@ -2834,7 +2889,7 @@ void GdbEngine::runDirectDebuggingHelper(const WatchData &data, bool dumpChildre
|
||||
|
||||
void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
|
||||
{
|
||||
if (q->startMode() == AttachCore) {
|
||||
if (!startModeAllowsDumpers()) {
|
||||
runDirectDebuggingHelper(data0, dumpChildren);
|
||||
return;
|
||||
}
|
||||
@@ -2867,7 +2922,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
|
||||
|
||||
QVariant var;
|
||||
var.setValue(data);
|
||||
execCommand(cmd, WatchUpdate, CB(handleDebuggingHelperValue1), var);
|
||||
execCommand(cmd, WatchUpdate | EmbedToken, CB(handleDebuggingHelperValue1), var);
|
||||
|
||||
q->showStatusMessage(
|
||||
tr("Retrieving data for watch view (%1 requests pending)...")
|
||||
@@ -3832,6 +3887,9 @@ void GdbEngine::tryLoadDebuggingHelpers()
|
||||
if (m_debuggingHelperState != DebuggingHelperUninitialized)
|
||||
return;
|
||||
|
||||
if (!startModeAllowsDumpers())
|
||||
return;
|
||||
|
||||
PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS");
|
||||
m_debuggingHelperState = DebuggingHelperUnavailable;
|
||||
if (!qq->qtDumperLibraryEnabled())
|
||||
@@ -3875,15 +3933,24 @@ void GdbEngine::tryLoadDebuggingHelpers()
|
||||
execCommand(_("sharedlibrary ") + dotEscape(lib));
|
||||
#endif
|
||||
// retreive list of dumpable classes
|
||||
execCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"));
|
||||
execCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"), EmbedToken);
|
||||
execCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
||||
}
|
||||
|
||||
void GdbEngine::recheckDebuggingHelperAvailability()
|
||||
{
|
||||
// retreive list of dumpable classes
|
||||
execCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"));
|
||||
execCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
||||
if (startModeAllowsDumpers()) {
|
||||
// retreive list of dumpable classes
|
||||
execCommand(_("call (void*)qDumpObjectData440(1,%1+1,0,0,0,0,0,0)"), EmbedToken);
|
||||
execCommand(_("p (char*)&qDumpOutBuffer"), CB(handleQueryDebuggingHelper));
|
||||
}
|
||||
}
|
||||
|
||||
bool GdbEngine::startModeAllowsDumpers() const
|
||||
{
|
||||
return q->startMode() == StartInternal
|
||||
|| q->startMode() == StartExternal
|
||||
|| q->startMode() == AttachExternal;
|
||||
}
|
||||
|
||||
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
|
||||
|
||||
@@ -147,7 +147,8 @@ public: // otherwise the Qt flag macros are unhappy
|
||||
NeedsStop = 1,
|
||||
Discardable = 2,
|
||||
RebuildModel = 4,
|
||||
WatchUpdate = Discardable|RebuildModel
|
||||
WatchUpdate = Discardable|RebuildModel,
|
||||
EmbedToken = 8
|
||||
};
|
||||
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
||||
private:
|
||||
@@ -191,6 +192,7 @@ private slots:
|
||||
void readDebugeeOutput(const QByteArray &data);
|
||||
void stubStarted();
|
||||
void stubError(const QString &msg);
|
||||
void uploadProcError(QProcess::ProcessError error);
|
||||
|
||||
private:
|
||||
int terminationIndex(const QByteArray &buffer, int &length);
|
||||
@@ -226,6 +228,7 @@ private:
|
||||
QByteArray m_inbuffer;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
QProcess m_uploadProc;
|
||||
|
||||
Core::Utils::ConsoleProcess m_stubProc;
|
||||
|
||||
@@ -354,6 +357,8 @@ private:
|
||||
const WatchData &parent);
|
||||
void setWatchDataType(WatchData &data, const GdbMi &mi);
|
||||
void setLocals(const QList<GdbMi> &locals);
|
||||
|
||||
bool startModeAllowsDumpers() const;
|
||||
|
||||
QString m_editedData;
|
||||
int m_pendingRequests;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AttachRemoteDialog</class>
|
||||
<widget class="QDialog" name="AttachRemoteDialog">
|
||||
<class>StartRemoteDialog</class>
|
||||
<widget class="QDialog" name="StartRemoteDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -49,6 +49,16 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="architectureComboBox"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="serverStartScriptLabel">
|
||||
<property name="text">
|
||||
<string>Server start script</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Core::Utils::PathChooser" name="serverStartScript" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -56,6 +56,12 @@
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#ifdef __GNUC__ // MinGW does not have a complete windows.h
|
||||
|
||||
typedef DWORD (__stdcall *PTHREAD_START_ROUTINE) (LPVOID lpThreadParameter);
|
||||
|
||||
#endif
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
static QString msgFuncFailed(const char *f, unsigned long error)
|
||||
@@ -68,7 +74,7 @@ template <class SymbolType>
|
||||
inline bool resolveSymbol(const char *libraryName, HMODULE libraryHandle, const char *symbolName, SymbolType *s, QString *errorMessage)
|
||||
{
|
||||
*s = 0;
|
||||
void *vs = ::GetProcAddress(libraryHandle, symbolName);
|
||||
FARPROC WINAPI vs = ::GetProcAddress(libraryHandle, symbolName);
|
||||
if (vs == 0) {
|
||||
*errorMessage = QString::fromLatin1("Unable to resolve '%2' in '%1'.").arg(QString::fromAscii(symbolName), QString::fromAscii(libraryName));
|
||||
return false;
|
||||
@@ -158,29 +164,29 @@ bool SharedLibraryInjector::hasLoaded(const QString &modulePath)
|
||||
|
||||
QString SharedLibraryInjector::findModule(const QString &moduleName)
|
||||
{
|
||||
const TCHAR *moduleNameC = moduleName.utf16();
|
||||
const TCHAR *moduleNameC = reinterpret_cast<const TCHAR*>(moduleName.utf16());
|
||||
if (GetFileAttributesW(moduleNameC) != INVALID_FILE_ATTRIBUTES)
|
||||
return moduleName;
|
||||
|
||||
TCHAR testpathC[MAX_PATH];
|
||||
// Check application path first
|
||||
GetModuleFileNameW(NULL, testpathC, MAX_PATH);
|
||||
QString testPath = QString::fromUtf16(testpathC);
|
||||
QString testPath = QString::fromUtf16(reinterpret_cast<unsigned short*>(testpathC));
|
||||
const int lastSlash = testPath.lastIndexOf(QLatin1Char('\\'));
|
||||
if (lastSlash != -1)
|
||||
testPath.truncate(lastSlash + 1);
|
||||
testPath += moduleName;
|
||||
if (GetFileAttributesW(testPath.utf16()) != INVALID_FILE_ATTRIBUTES)
|
||||
if (GetFileAttributesW(reinterpret_cast<const TCHAR*>(testPath.utf16())) != INVALID_FILE_ATTRIBUTES)
|
||||
return testPath;
|
||||
// Path Search
|
||||
if (SearchPathW(NULL, moduleName.utf16(), NULL, sizeof(testpathC)/2, testpathC, NULL))
|
||||
return QString::fromUtf16(testpathC);
|
||||
if (SearchPathW(NULL, reinterpret_cast<const TCHAR*>(moduleName.utf16()), NULL, sizeof(testpathC)/2, testpathC, NULL))
|
||||
return QString::fromUtf16(reinterpret_cast<unsigned short*>(testpathC));
|
||||
// Last chance, if the module has already been loaded in this process, then use that path
|
||||
const HMODULE loadedModule = GetModuleHandleW(moduleName.utf16());
|
||||
const HMODULE loadedModule = GetModuleHandleW(reinterpret_cast<const TCHAR*>(moduleName.utf16()));
|
||||
if (loadedModule) {
|
||||
GetModuleFileNameW(loadedModule, testpathC, sizeof(testpathC));
|
||||
if (GetFileAttributes(testpathC) != INVALID_FILE_ATTRIBUTES)
|
||||
return QString::fromUtf16(testpathC);
|
||||
return QString::fromUtf16(reinterpret_cast<unsigned short*>(testpathC));
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
@@ -188,13 +194,13 @@ QString SharedLibraryInjector::findModule(const QString &moduleName)
|
||||
unsigned long SharedLibraryInjector::getModuleEntryPoint(const QString &moduleName)
|
||||
{
|
||||
// If file doesn't exist, just treat it like we cannot figure out the entry point
|
||||
if (moduleName.isEmpty() || GetFileAttributesW(moduleName.utf16()) == INVALID_FILE_ATTRIBUTES)
|
||||
if (moduleName.isEmpty() || GetFileAttributesW(reinterpret_cast<const TCHAR*>(moduleName.utf16())) == INVALID_FILE_ATTRIBUTES)
|
||||
return 0;
|
||||
|
||||
// Read the first 1K of data from the file
|
||||
unsigned char peData[1024];
|
||||
unsigned long peDataSize = 0;
|
||||
const HANDLE hFile = CreateFileW(moduleName.utf16(), FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
const HANDLE hFile = CreateFileW(reinterpret_cast<const WCHAR*>(moduleName.utf16()), FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (hFile == INVALID_HANDLE_VALUE
|
||||
|| !ReadFile(hFile, peData, sizeof(peData), &peDataSize, NULL))
|
||||
return 0;
|
||||
@@ -236,7 +242,7 @@ bool SharedLibraryInjector::escalatePrivileges(QString *errorMessage)
|
||||
Debug_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // set to enable privilege
|
||||
Debug_Privileges.PrivilegeCount = 1; // working with only 1
|
||||
|
||||
if (!OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
|
||||
*errorMessage = msgFuncFailed("OpenProcessToken", GetLastError());
|
||||
break;
|
||||
}
|
||||
@@ -289,8 +295,8 @@ bool SharedLibraryInjector::doStubInjection(unsigned long pid,
|
||||
|
||||
if (!escalatePrivileges(errorMessage))
|
||||
return false;
|
||||
|
||||
#if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
|
||||
// MinGW lacks OpenThread() and the advapi.lib as of 6.5.2009
|
||||
#if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) || defined(__GNUC__)
|
||||
*errorMessage = QLatin1String("Not implemented for this architecture.");
|
||||
return false;
|
||||
#else
|
||||
@@ -462,7 +468,7 @@ HMODULE SharedLibraryInjector::findModuleHandle(const QString &modulePath, QStri
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TCHAR szModName[MAX_PATH];
|
||||
if (m_pfnGetModuleFileNameExW(hProcess, hMods[i], szModName, sizeof(szModName))) {
|
||||
if (QString::fromUtf16(szModName) == modulePath) {
|
||||
if (QString::fromUtf16(reinterpret_cast<const unsigned short *>(szModName)) == modulePath) {
|
||||
::FreeLibrary(m_hModPSAPI);
|
||||
::CloseHandle(hProcess);
|
||||
return hMods[i];
|
||||
|
||||
@@ -7,5 +7,8 @@ HEADERS += $$PWD/peutils.h \
|
||||
$$PWD/dbgwinutils.h \
|
||||
$$PWD/sharedlibraryinjector.h
|
||||
|
||||
# For the Privilege manipulation functions in sharedlibraryinjector.cpp
|
||||
LIBS += advapi32.lib
|
||||
contains(QMAKE_CXX, cl) {
|
||||
# For the Privilege manipulation functions in sharedlibraryinjector.cpp.
|
||||
# Not required for MinGW.
|
||||
LIBS += advapi32.lib
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ void FindToolWindow::writeSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
settings->beginGroup("Find");
|
||||
settings->setValue("CurrentFilter", m_currentFilter ? 0 : m_currentFilter->id());
|
||||
settings->setValue("CurrentFilter", m_currentFilter ? m_currentFilter->id() : 0);
|
||||
foreach (IFindFilter *filter, m_filters)
|
||||
filter->writeSettings(settings);
|
||||
settings->endGroup();
|
||||
|
||||
@@ -131,8 +131,6 @@ ProjectWindow::~ProjectWindow()
|
||||
|
||||
void ProjectWindow::restoreStatus()
|
||||
{
|
||||
m_panelsTabWidget->setFocus();
|
||||
|
||||
if (!m_treeWidget->currentItem() && m_treeWidget->topLevelItemCount()) {
|
||||
m_treeWidget->setCurrentItem(m_treeWidget->topLevelItem(0), 0, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
IDE_BUILD_TREE = $$OUT_PWD/../../..
|
||||
include(../qtcreator.pri)
|
||||
|
||||
win32 {
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
isEmpty(IDE_BUILD_TREE) {
|
||||
IDE_BUILD_TREE = $$OUT_PWD/../../..
|
||||
}
|
||||
include(../qtcreator.pri)
|
||||
|
||||
isEmpty(PROVIDER) {
|
||||
@@ -17,25 +14,17 @@ isEmpty(TARGET) {
|
||||
error("qworkbenchplugin.pri: You must provide a TARGET")
|
||||
}
|
||||
|
||||
# Copy the pluginspec file to the library directory.
|
||||
# Note: On Windows/MinGW with some sh.exe in the path,
|
||||
# QMAKE_COPY is some cp command that does not understand
|
||||
# "\". Force the standard windows copy.
|
||||
COPYDEST = $${DESTDIR}
|
||||
COPYSRC = $${_PRO_FILE_PWD_}/$${TARGET}.pluginspec
|
||||
PLUGINSPECS = $${_PRO_FILE_PWD_}/$${TARGET}.pluginspec
|
||||
copy2build.input = PLUGINSPECS
|
||||
copy2build.output = $$DESTDIR/${QMAKE_FUNC_FILE_IN_stripSrcDir}
|
||||
isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS
|
||||
copy2build.commands = $$QMAKE_COPY \"${QMAKE_FILE_IN}\" \"${QMAKE_FILE_OUT}\"
|
||||
copy2build.name = COPY ${QMAKE_FILE_IN}
|
||||
copy2build.CONFIG += no_link
|
||||
QMAKE_EXTRA_COMPILERS += copy2build
|
||||
|
||||
TARGET = $$qtLibraryTarget($$TARGET)
|
||||
|
||||
win32 {
|
||||
COPYDEST ~= s|/+|\|
|
||||
COPYSRC ~= s|/+|\|
|
||||
COPY_CMD=xcopy /y
|
||||
} else {
|
||||
COPY_CMD=$${QMAKE_COPY}
|
||||
}
|
||||
|
||||
QMAKE_POST_LINK += $${COPY_CMD} $${COPYSRC} $${COPYDEST}
|
||||
|
||||
macx {
|
||||
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../PlugIns/$${PROVIDER}/
|
||||
} else:linux-* {
|
||||
|
||||
15
tests/manual/fakevim/runremotely.sh
Executable file
15
tests/manual/fakevim/runremotely.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
account=berlin@hd
|
||||
sourcedir=/data5/dev/creator/tests/manual/fakevim/
|
||||
exename=fakevim
|
||||
targetdir=/tmp/run-${exename}
|
||||
|
||||
executable=${sourcedir}/${exename}
|
||||
qtlibs=`ldd ${executable} | grep libQt | sed -e 's/^.*=> \(.*\) (.*)$/\1/'`
|
||||
|
||||
ssh ${account} "mkdir -p ${targetdir}"
|
||||
scp ${executable} ${qtlibs} ${account}:${targetdir}
|
||||
ssh ${account} "chrpath -r ${targetdir} ${targetdir}/*"
|
||||
ssh ${account} "gdbserver localhost:5555 ${targetdir}/${exename}"
|
||||
ssh ${account} "rm ${targetdir}/* ; rmdir ${targetdir}"
|
||||
|
||||
Reference in New Issue
Block a user