Merge remote-tracking branch 'origin/4.1'

Change-Id: Ieaddc6093d10c08a54acb9b57cbbfe022bc3c038
This commit is contained in:
Orgad Shaneh
2016-09-22 11:01:16 +03:00
21 changed files with 1969 additions and 887 deletions

View File

@@ -46,9 +46,22 @@
\section1 Configuring Devices
The process of configuring devices and the UI varies slightly depending on
the Xcode version that you use. The instructions in this section describe
the process and UI when using Xcode version 4.6.3.
The connections between \QC and an iOS device are protected by using a
certificate that you receive from Apple when you
\l{https://developer.apple.com/programs/enroll/}
{enroll in the Apple Developer Program}. The certificate is copied to
the device when you configure the device.
The first time you connect the device to the Mac, you are asked to enable
developer mode on the device. The next time you connect the device, \QC
detects it automatically. To disable automatic connections to a device that
you do not use for development, select \uicontrol Preferences >
\uicontrol iOS, and deselect the \uicontrol {Ask about devices not in
developer mode} check box.
\note The process of configuring devices and the UI varies slightly
depending on the Xcode version that you use. We recommend that you use the
latest available Xcode version.
To configure connections between \QC and an iOS device:
@@ -58,43 +71,11 @@
\li Connect the device to the Mac computer with a USB cable.
\li Start Xcode to configure the device:
\li Start Xcode to configure the device.
\list 1
\li Select \uicontrol Window > \uicontrol Organizer.
\li Select the \uicontrol + button to add the connected device.
\li Select the device you want to add in the list of devices.
\li If you do not have an Apple developer account, you can now
create one, for a charge.
\li When your account is ready, you can add the device. Your
Apple developer certificate is copied to the device.
\li The first time you connect the device, you are asked to
enable developer mode on the device.
\endlist
The connections between \QC and an iOS device are protected by using an
iOS Developer Program certificate that you receive from Apple for a
charge when you
\l{http://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/EnrollingADP/EnrollingADP.html}
{enroll in the iOS Developer Program}. The certificate is copied to the
device when you configure the device.
The next time you connect the device to the Mac computer, \QC
detects it automatically. To disable automatic connections to a
device that you do not use for development, select \uicontrol Preferences >
\uicontrol iOS, and deselect the
\uicontrol {Ask about devices not in developer mode} check box.
\note If \QC does not detect the devices, the iOS plugin might not be
enabled. Select \uicontrol {Qt Creator} > \uicontrol {About Plugins} >
\uicontrol {Device Support} > \uicontrol iOS and restart \QC.
For example, in Xcode version 7.3.0, select \uicontrol Window >
\uicontrol Device > \uicontrol + > \uicontrol {Add Device} to add
the connected device.
\li To specify build settings:
@@ -103,8 +84,9 @@
\li Open a project for an application you want to develop for the
device.
\li Select \uicontrol Projects > \uicontrol {Build & Run} > \uicontrol {Add Kit} to
add a kit for building and running applications on iOS.
\li Select \uicontrol Projects > \uicontrol {Build & Run} >
\uicontrol {Add Kit} to add a kit for building and running
applications on iOS.
\image qtcreator-ios-add-kit.png "Build & Run Settings"
@@ -123,9 +105,10 @@
\endlist
\note If you cannot deploy applications, because a provisioning profile is
missing, try refreshing the list of provisioning profiles in Xcode. Select
\uicontrol Xcode > \uicontrol Preferences > \uicontrol Accounts > \uicontrol {View Details}, and
then select the \uicontrol Refresh button.
missing, check that provisioning profiles are listed in Xcode by selecting
\uicontrol Xcode > \uicontrol Preferences > \uicontrol Accounts >
\uicontrol {View Details}. For more information about how to acquire and
install a provisioning profile, see Apple documentation.
\section1 Viewing Device Connection Status

View File

@@ -724,8 +724,13 @@ class Dumper(DumperBase):
self.report('pid="%s"' % self.process.GetProcessID())
# Even if it stops it seems that LLDB assumes it is running
# and later detects that it did stop after all, so it is be
# better to mirror that and wait for the spontaneous stop.
self.reportState("enginerunandinferiorrunok")
# better to mirror that and wait for the spontaneous stop
if self.process and self.process.GetState() == lldb.eStateStopped:
# lldb stops the process after attaching. This happens before the
# eventloop starts. Relay the correct state back.
self.reportState("enginerunandinferiorstopok")
else:
self.reportState("enginerunandinferiorrunok")
elif self.startMode_ == AttachToRemoteServer or self.startMode_ == AttachToRemoteProcess:
self.process = self.target.ConnectRemote(
self.debugger.GetListener(),

File diff suppressed because it is too large Load Diff

View File

@@ -231,7 +231,7 @@ void DebuggerItemManager::autoDetectGdbOrLldbDebuggers()
= lldbInfo.runBlocking(QLatin1String("xcrun"), QStringList() << QLatin1String("--find")
<< QLatin1String("lldb"));
if (response.result == Utils::SynchronousProcessResponse::Finished) {
QString lPath = response.allOutput();
QString lPath = response.allOutput().trimmed();
if (!lPath.isEmpty()) {
const QFileInfo fi(lPath);
if (fi.exists() && fi.isExecutable() && !fi.isDir())

View File

@@ -940,9 +940,10 @@ void LldbEngine::handleStateNotification(const GdbMi &reportedState)
if (runParameters().continueAfterAttach)
m_continueAtNextSpontaneousStop = true;
notifyEngineRunAndInferiorRunOk();
} else if (newState == "enginerunandinferiorstopok")
} else if (newState == "enginerunandinferiorstopok") {
notifyEngineRunAndInferiorStopOk();
else if (newState == "enginerunokandinferiorunrunnable")
continueInferior();
} else if (newState == "enginerunokandinferiorunrunnable")
notifyEngineRunOkAndInferiorUnrunnable();
else if (newState == "inferiorshutdownok")
notifyInferiorShutdownOk();

View File

@@ -42,29 +42,6 @@ using namespace VcsBase;
namespace Git {
namespace Internal {
class MergeToolProcess : public QProcess
{
public:
MergeToolProcess(QObject *parent = 0) : QProcess(parent)
{ }
protected:
qint64 readData(char *data, qint64 maxlen) override
{
qint64 res = QProcess::readData(data, maxlen);
if (res > 0)
VcsOutputWindow::append(QString::fromLocal8Bit(data, int(res)));
return res;
}
qint64 writeData(const char *data, qint64 len) override
{
if (len > 0)
VcsOutputWindow::append(QString::fromLocal8Bit(data, int(len)));
return QProcess::writeData(data, len);
}
};
MergeTool::MergeTool(QObject *parent) : QObject(parent)
{ }
@@ -77,7 +54,7 @@ bool MergeTool::start(const QString &workingDirectory, const QStringList &files)
{
QStringList arguments;
arguments << "mergetool" << "-y" << files;
m_process = new MergeToolProcess(this);
m_process = new QProcess(this);
m_process->setWorkingDirectory(workingDirectory);
const Utils::FileName binary = GitPlugin::client()->vcsBinary();
VcsOutputWindow::appendCommand(workingDirectory, binary, arguments);
@@ -93,16 +70,9 @@ bool MergeTool::start(const QString &workingDirectory, const QStringList &files)
return true;
}
MergeTool::FileState MergeTool::waitAndReadStatus(QString &extraInfo)
MergeTool::FileState MergeTool::parseStatus(const QByteArray &line, QString &extraInfo)
{
QByteArray state;
for (int i = 0; i < 5; ++i) {
if (m_process->canReadLine()) {
state = m_process->readLine().trimmed();
break;
}
m_process->waitForReadyRead(500);
}
QByteArray state = line.trimmed();
// " {local}: modified file"
// " {remote}: deleted"
if (!state.isEmpty()) {
@@ -209,8 +179,7 @@ void MergeTool::chooseAction()
key = QVariant('a'); // abort
ba.append(key.toChar().toLatin1());
ba.append('\n');
m_process->write(ba);
m_process->waitForBytesWritten();
write(ba);
}
void MergeTool::addButton(QMessageBox *msgBox, const QString &text, char key)
@@ -223,25 +192,27 @@ void MergeTool::prompt(const QString &title, const QString &question)
if (QMessageBox::question(Core::ICore::dialogParent(), title, question,
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No) == QMessageBox::Yes) {
m_process->write("y\n");
write("y\n");
} else {
m_process->write("n\n");
write("n\n");
}
m_process->waitForBytesWritten();
}
void MergeTool::readData()
{
while (m_process->bytesAvailable()) {
QByteArray line = m_process->canReadLine() ? m_process->readLine() : m_process->readAllStandardOutput();
VcsOutputWindow::append(QString::fromLocal8Bit(line));
// {Normal|Deleted|Submodule|Symbolic link} merge conflict for 'foo.cpp'
int index = line.indexOf(" merge conflict for ");
if (index != -1) {
m_mergeType = mergeType(line.left(index));
int quote = line.indexOf('\'');
m_fileName = QString::fromLocal8Bit(line.mid(quote + 1, line.lastIndexOf('\'') - quote - 1));
m_localState = waitAndReadStatus(m_localInfo);
m_remoteState = waitAndReadStatus(m_remoteInfo);
} else if (line.startsWith(" {local}")) {
m_localState = parseStatus(line, m_localInfo);
} else if (line.startsWith(" {remote}")) {
m_remoteState = parseStatus(line, m_remoteInfo);
chooseAction();
} else if (line.startsWith("Was the merge successful")) {
prompt(tr("Unchanged File"), tr("Was the merge successful?"));
@@ -266,5 +237,12 @@ void MergeTool::done()
deleteLater();
}
void MergeTool::write(const QByteArray &bytes)
{
m_process->write(bytes);
m_process->waitForBytesWritten();
VcsOutputWindow::append(QString::fromLocal8Bit(bytes));
}
} // namespace Internal
} // namespace Git

View File

@@ -30,12 +30,12 @@
QT_BEGIN_NAMESPACE
class QMessageBox;
class QProcess;
QT_END_NAMESPACE
namespace Git {
namespace Internal {
class MergeToolProcess;
class GitClient;
class MergeTool : public QObject
@@ -67,14 +67,15 @@ private:
void prompt(const QString &title, const QString &question);
void readData();
void done();
void write(const QByteArray &bytes);
FileState waitAndReadStatus(QString &extraInfo);
FileState parseStatus(const QByteArray &line, QString &extraInfo);
QString mergeTypeName();
QString stateName(FileState state, const QString &extraInfo);
void chooseAction();
void addButton(QMessageBox *msgBox, const QString &text, char key);
MergeToolProcess *m_process = nullptr;
QProcess *m_process = nullptr;
MergeType m_mergeType = NormalMerge;
QString m_fileName;
FileState m_localState = UnknownState;

View File

@@ -143,8 +143,14 @@ RunControl *IosDebugSupport::createDebugRunControl(IosRunConfiguration *runConfi
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT);
}
}
if (qmlDebug && !cppDebug) {
params.startMode = AttachToRemoteServer;
if (qmlDebug) {
QTcpServer server;
QTC_ASSERT(server.listen(QHostAddress::LocalHost)
|| server.listen(QHostAddress::LocalHostIPv6), return 0);
params.qmlServer.host = server.serverAddress().toString();
if (!cppDebug)
params.startMode = AttachToRemoteServer;
}
DebuggerRunControl *debuggerRunControl = createDebuggerRunControl(params, runConfig, errorMessage);

View File

@@ -116,5 +116,6 @@ QSet<Core::Id> IosQtVersion::availableFeatures() const
QSet<Core::Id> IosQtVersion::targetDeviceTypes() const
{
return { Constants::IOS_DEVICE_TYPE };
// iOS Qt version supports ios devices as well as simulator.
return { Constants::IOS_DEVICE_TYPE, Constants::IOS_SIMULATOR_TYPE };
}

View File

@@ -123,7 +123,7 @@ public:
};
explicit IosToolHandlerPrivate(const IosDeviceType &devType, IosToolHandler *q);
virtual ~IosToolHandlerPrivate() {}
virtual ~IosToolHandlerPrivate();
virtual void requestTransferApp(const QString &bundlePath, const QString &deviceId,
int timeout = 1000) = 0;
virtual void requestRunApp(const QString &bundlePath, const QStringList &extraArgs,
@@ -158,7 +158,7 @@ protected:
void processXml();
IosToolHandler *q;
QProcess process;
QProcess *process;
QTimer killTimer;
QXmlStreamReader outputParser;
QString deviceId;
@@ -202,7 +202,12 @@ private:
IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType,
Ios::IosToolHandler *q) :
q(q), state(NonStarted), devType(devType), iBegin(0), iEnd(0),
q(q),
process(new QProcess),
state(NonStarted),
devType(devType),
iBegin(0),
iEnd(0),
gdbSocket(-1)
{
killTimer.setSingleShot(true);
@@ -225,20 +230,30 @@ IosToolHandlerPrivate::IosToolHandlerPrivate(const IosDeviceType &devType,
<< QLatin1String("/System/Library/PrivateFrameworks");
env.insert(QLatin1String("DYLD_FALLBACK_FRAMEWORK_PATH"), frameworkPaths.join(QLatin1Char(':')));
qCDebug(toolHandlerLog) << "IosToolHandler runEnv:" << env.toStringList();
process.setProcessEnvironment(env);
QObject::connect(&process, &QProcess::readyReadStandardOutput,
process->setProcessEnvironment(env);
QObject::connect(process, &QProcess::readyReadStandardOutput,
q, &IosToolHandler::subprocessHasData);
QObject::connect(&process,
QObject::connect(process,
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
q, &IosToolHandler::subprocessFinished);
QObject::connect(&process, &QProcess::errorOccurred, q, &IosToolHandler::subprocessError);
QObject::connect(process, &QProcess::errorOccurred, q, &IosToolHandler::subprocessError);
QObject::connect(&killTimer, &QTimer::timeout,
q, &IosToolHandler::killProcess);
}
IosToolHandlerPrivate::~IosToolHandlerPrivate()
{
if (isRunning()) {
process->terminate();
if (!process->waitForFinished(1000))
process->kill();
}
delete process;
}
bool IosToolHandlerPrivate::isRunning()
{
return process.state() != QProcess::NotRunning;
return process && (process->state() != QProcess::NotRunning);
}
void IosToolHandlerPrivate::start(const QString &exe, const QStringList &args)
@@ -246,7 +261,7 @@ void IosToolHandlerPrivate::start(const QString &exe, const QStringList &args)
QTC_CHECK(state == NonStarted);
state = Starting;
qCDebug(toolHandlerLog) << "running " << exe << args;
process.start(exe, args);
process->start(exe, args);
state = StartedInferior;
}
@@ -281,9 +296,9 @@ void IosToolHandlerPrivate::stop(int errorCode)
case Stopped:
return;
}
if (process.state() != QProcess::NotRunning) {
process.write("k\n\r");
process.closeWriteChannel();
if (isRunning()) {
process->write("k\n\r");
process->closeWriteChannel();
killTimer.start(1500);
}
}
@@ -554,8 +569,8 @@ void IosToolHandlerPrivate::subprocessHasData()
// read some data
{
char buf[200];
while (true) {
qint64 rRead = process.read(buf, sizeof(buf));
while (isRunning()) {
qint64 rRead = process->read(buf, sizeof(buf));
if (rRead == -1) {
stop(-1);
return;
@@ -704,8 +719,8 @@ void IosSimulatorToolHandlerPrivate::addDeviceArguments(QStringList &args) const
void IosToolHandlerPrivate::killProcess()
{
if (process.state() != QProcess::NotRunning)
process.kill();
if (isRunning())
process->kill();
}
} // namespace Internal

View File

@@ -56,7 +56,7 @@ public:
Abi targetAbi() const override;
QString originalTargetTriple() const override;
QString version() const;
QList<Abi> supportedAbis() const;
QList<Abi> supportedAbis() const override;
void setTargetAbi(const Abi &);
bool isValid() const override;

View File

@@ -819,7 +819,7 @@ QVector<int> MiniProjectTargetSelector::listWidgetWidths(int minSize, int maxSiz
}
widthToDistribute -= delta * i;
if (widthToDistribute == 0)
if (widthToDistribute <= 0)
return result;
first = result[indexes.first()];

View File

@@ -149,6 +149,11 @@ Core::Id ToolChain::typeId() const
return d->m_typeId;
}
QList<Abi> ToolChain::supportedAbis() const
{
return { targetAbi() };
}
const QSet<ToolChain::Language> &ToolChain::allLanguages()
{
static QSet<Language> languages({ Language::C, Language::Cxx });

View File

@@ -81,6 +81,7 @@ public:
Core::Id typeId() const;
virtual QString typeDisplayName() const = 0;
virtual Abi targetAbi() const = 0;
virtual QList<Abi> supportedAbis() const;
virtual QString originalTargetTriple() const { return QString(); }
virtual bool isValid() const = 0;

View File

@@ -342,8 +342,11 @@ QList<ToolChain *> ToolChainManager::findToolChains(const Abi &abi)
{
QList<ToolChain *> result;
foreach (ToolChain *tc, d->m_toolChains) {
Abi targetAbi = tc->targetAbi();
if (targetAbi.isCompatibleWith(abi))
bool isCompatible = Utils::anyOf(tc->supportedAbis(), [abi](const Abi &supportedAbi) {
return supportedAbi.isCompatibleWith(abi);
});
if (isCompatible)
result.append(tc);
}
return result;

View File

@@ -99,7 +99,7 @@ void DebugMessagesModel::loadEvent(const QmlEvent &event, const QmlEventType &ty
m_data.insert(insert(event.timestamp(), 0, type.detailType()),
MessageData(event.string(), event.typeIndex()));
if (type.detailType() > m_maximumMsgType)
m_maximumMsgType = event.typeIndex();
m_maximumMsgType = type.detailType();
}
void DebugMessagesModel::finalize()

View File

@@ -44,7 +44,9 @@ FlameGraphModel::FlameGraphModel(QmlProfilerModelManager *modelManager,
{
m_modelManager = modelManager;
m_callStack.append(QmlEvent());
m_stackTop = &m_stackBottom;
m_compileStack.append(QmlEvent());
m_callStackTop = &m_stackBottom;
m_compileStackTop = &m_stackBottom;
connect(modelManager, &QmlProfilerModelManager::stateChanged,
this, &FlameGraphModel::onModelManagerStateChanged);
connect(modelManager->notesModel(), &Timeline::TimelineNotesModel::changed,
@@ -64,8 +66,11 @@ void FlameGraphModel::clear()
beginResetModel();
m_stackBottom = FlameGraphData(0, -1, 1);
m_callStack.clear();
m_compileStack.clear();
m_callStack.append(QmlEvent());
m_stackTop = &m_stackBottom;
m_compileStack.append(QmlEvent());
m_callStackTop = &m_stackBottom;
m_compileStackTop = &m_stackBottom;
m_typeIdsWithNotes.clear();
endResetModel();
}
@@ -99,7 +104,11 @@ void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
if (m_stackBottom.children.isEmpty())
beginResetModel();
const QmlEvent *potentialParent = &(m_callStack.top());
const bool isCompiling = (type.rangeType() == Compiling);
QStack<QmlEvent> &stack = isCompiling ? m_compileStack : m_callStack;
FlameGraphData *&stackTop = isCompiling ? m_compileStackTop : m_callStackTop;
const QmlEvent *potentialParent = &(stack.top());
if (type.message() == MemoryAllocation) {
if (type.detailType() == HeapPage)
return; // We're only interested in actual allocations, not heap pages being mmap'd
@@ -108,20 +117,20 @@ void FlameGraphModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
if (amount < 0)
return; // We're not interested in GC runs here
for (FlameGraphData *data = m_stackTop; data; data = data->parent) {
for (FlameGraphData *data = stackTop; data; data = data->parent) {
++data->allocations;
data->memory += amount;
}
} else if (event.rangeStage() == RangeEnd) {
m_stackTop->duration += event.timestamp() - potentialParent->timestamp();
m_callStack.pop();
m_stackTop = m_stackTop->parent;
potentialParent = &(m_callStack.top());
stackTop->duration += event.timestamp() - potentialParent->timestamp();
stack.pop();
stackTop = stackTop->parent;
potentialParent = &(stack.top());
} else {
QTC_ASSERT(event.rangeStage() == RangeStart, return);
m_callStack.push(event);
m_stackTop = pushChild(m_stackTop, event);
stack.push(event);
stackTop = pushChild(stackTop, event);
}
}

View File

@@ -101,8 +101,10 @@ private:
// used by binding loop detection
QStack<QmlEvent> m_callStack;
QStack<QmlEvent> m_compileStack;
FlameGraphData m_stackBottom;
FlameGraphData *m_stackTop;
FlameGraphData *m_callStackTop;
FlameGraphData *m_compileStackTop;
int m_modelId;
QmlProfilerModelManager *m_modelManager;

View File

@@ -36,7 +36,7 @@ MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *pa
QmlProfilerTimelineModel(manager, MemoryAllocation, MaximumRangeType, ProfileMemory, parent)
{
// Announce additional features. The base class already announces the main feature.
announceFeatures(Constants::QML_JS_RANGE_FEATURES);
announceFeatures(Constants::QML_JS_RANGE_FEATURES ^ (1 << ProfileCompiling));
}
int MemoryUsageModel::rowMaxValue(int rowNumber) const
@@ -128,7 +128,8 @@ QVariantMap MemoryUsageModel::details(int index) const
bool MemoryUsageModel::accepted(const QmlEventType &type) const
{
return QmlProfilerTimelineModel::accepted(type) || type.rangeType() != MaximumRangeType;
return QmlProfilerTimelineModel::accepted(type)
|| (type.rangeType() != MaximumRangeType && type.rangeType() != Compiling);
}
void MemoryUsageModel::loadEvent(const QmlEvent &event, const QmlEventType &type)
@@ -258,6 +259,14 @@ void MemoryUsageModel::clear()
QmlProfilerTimelineModel::clear();
}
bool MemoryUsageModel::handlesTypeId(int typeId) const
{
Q_UNUSED(typeId);
// We don't want the memory ranges allocated by some QML/JS function to be highlighted when
// propagating a typeId selection to the timeline. The actual range should be highlighted.
return false;
}
MemoryUsageModel::MemoryAllocationItem::MemoryAllocationItem(int typeId, qint64 baseAmount) :
size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0),
typeId(typeId)

View File

@@ -71,6 +71,7 @@ public:
void loadEvent(const QmlEvent &event, const QmlEventType &type) override;
void finalize() override;
void clear() override;
bool handlesTypeId(int typeId) const override;
private:
struct RangeStackFrame {

View File

@@ -242,7 +242,11 @@ void SubmitEditorWidget::registerActions(QAction *editorUndoAction, QAction *edi
d->m_ui.buttonLayout->addWidget(d->m_submitButton);
if (!d->m_submitShortcut)
d->m_submitShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return), this);
connect(d->m_submitShortcut, &QShortcut::activated, submitAction, &QAction::trigger);
connect(d->m_submitShortcut, &QShortcut::activated,
submitAction, [submitAction] {
if (submitAction->isEnabled())
submitAction->trigger();
});
}
if (diffAction) {
if (debug)