Merge remote-tracking branch 'origin/3.1'

This commit is contained in:
Eike Ziller
2014-04-03 10:16:14 +02:00
23 changed files with 379 additions and 61 deletions

14
dist/changes-3.1.0 vendored
View File

@@ -26,6 +26,7 @@ Editing
Managing and Building Projects
* Re-added option to import existing builds even after project configuration (QTCREATORBUG-7836)
* Fixed that compiler output in issues list was not using monospace font (QTCREATORBUG-11345)
* Fixed crash when removing run configuration that was about to be run (QTCREATORBUG-11594)
QMake Projects
* Added context menu item "Add Existing Directory" that adds all
@@ -46,20 +47,24 @@ Debugging
* Removed support for GDB without Python
* Added context menu item for saving backtrace as tasks-file
* GDB, LLDB
* Added pretty printer for std::unordered_set
* Added pretty printers for std::unordered_set and boost::container::list
* Fixed various pretty printers
* CDB
* Added pretty printer for std::complex and C++11 std::array
* LLDB
* Added support for debugging applications that run in terminal (QTCREATORBUG-9650)
* Added support for "Create Full Backtrace" (QTCREATORBUG-11642)
* Fixed that debugging was not possible with MallocScribble environment variable set
(QTCREATORBUG-11371)
* Fixed "Jump to Line", "Run to Line" and "Jump to Address"
* Fixed updating breakpoint locations while debugging (QTCREATORBUG-11564)
QML Profiler
* Improved performance (QTCREATORBUG-10950)
* Improved layout of details views
* Added JavaScript calls in Events view and Timeline view
* Fixed opening files from JavaScript profiling output (QTCREATORBUG-11094)
* Fixed hovering over narrow items in Timeline view (QTCREATORBUG-11692)
C++ Support
* Added code model inspector
@@ -72,6 +77,7 @@ C++ Support
* Fixed syntax highlighting of multiline strings and comments (QTCREATORBUG-662)
* Fixed that symbol dropdown was jumping to the wrong editor (QTCREATORBUG-11157)
* Fixed highlighting when #undef is used (QTCREATORBUG-10454)
* Fixed issue with follow symbol and overloaded functions (QTCREATORBUG-10295)
* Improved the Insert Virtual Functions refactoring action:
* Check only pure virtual functions by default
* Display all overrides of a function
@@ -131,6 +137,7 @@ QNX
* Added support for attaching debugger to running applications
* Fixed several issues with certificate password dialog in BlackBerry
options (QTCREATORBUG-10948)
* Fixed mkspec setting in the qmake build step (QTCREATORBUG-11674)
Android
* Made it possible to cancel waiting for an AVD to boot up
@@ -146,9 +153,14 @@ Android
* Fixed that Qt Creator restart was required after configuring Android SDK (QTCREATORBUG-10936)
iOS
* Enabled iOS support by default
* Added support for QML debugging
* Added check for already running application on device
* Added automatic detection that developer mode becomes activated on connected device
WinRT
* Added experimental support
Credits for these changes go to:
Alessandro Portale

View File

@@ -7213,7 +7213,7 @@ Add, modify, and remove document filters, which determine the documentation set
</message>
<message>
<source>Error while building/deploying project %1 (kit: %2)</source>
<translation>Fehler beim Erstellen/Deployment des Projekts %1(Kit: %2)</translation>
<translation>Fehler beim Erstellen/Deployment des Projekts %1 (Kit: %2)</translation>
</message>
<message>
<source>When executing step &apos;%1&apos;</source>

View File

@@ -56,8 +56,13 @@ Rectangle {
anchors.right: parent.right
anchors.leftMargin: 18
text: examplesModel.readSearchStringsFromSettings()
placeholderText: qsTr("Search in Examples...")
onTextChanged: examplesModel.parseSearchString(text)
onTextChanged: {
examplesModel.parseSearchString(text);
examplesModel.writeSearchStringToSettings(text);
}
}
ComboBox {

View File

@@ -140,7 +140,7 @@ ColumnLayout {
IconAndLink {
iconSource: "images/icons/qt_cloud.png"
title: qsTr("Qt Cloud Services")
openUrl: "https://developer.qtc.io?utm_source=qtcreator31"
openUrl: "https://developer.qtcloudservices.com?utm_source=qtcreator31"
}
IconAndLink {
iconSource: "images/icons/onlineCommunity.png"

View File

@@ -1763,6 +1763,13 @@ void GdbEngine::handlePythonSetup(const GdbResponse &response)
showMessage(_("ENGINE SUCCESSFULLY STARTED"));
notifyEngineSetupOk();
} else {
QByteArray msg = response.data["msg"].data();
if (msg.contains("Python scripting is not supported in this copy of GDB.")) {
QString out1 = _("The selected build of GDB does not support Python scripting.");
QString out2 = _("It cannot be used in Qt Creator.");
showStatusMessage(out1 + QLatin1Char(' ') + out2);
showMessageBox(QMessageBox::Critical, tr("Execution Error"), out1 + _("<br>") + out2);
}
notifyEngineSetupFailed();
}
}

View File

@@ -2123,6 +2123,7 @@ void FakeVimPluginPrivate::showExtraInformation(const QString &text)
IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8());
EditorManager::activateEditor(iedit);
FakeVimHandler *handler = m_editorToHandler.value(iedit, 0);
QTC_ASSERT(handler, return);
handler->handleCommand(_("0"));
}

View File

@@ -243,17 +243,11 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
const QString &batchArgs,
QMap<QString, QString> &envPairs)
{
const QByteArray marker = "####################\r\n";
// Create a temporary file name for the output. Use a temporary file here
// as I don't know another way to do this in Qt...
// Note, can't just use a QTemporaryFile all the way through as it remains open
// internally so it can't be streamed to later.
QString tempOutFile;
QTemporaryFile* pVarsTempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/XXXXXX.txt"));
pVarsTempFile->setAutoRemove(false);
pVarsTempFile->open();
pVarsTempFile->close();
tempOutFile = pVarsTempFile->fileName();
delete pVarsTempFile;
// Create a batch file to create and save the env settings
Utils::TempFileSaver saver(QDir::tempPath() + QLatin1String("/XXXXXX.bat"));
@@ -265,10 +259,9 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
call += batchArgs.toLocal8Bit();
}
saver.write(call + "\r\n");
const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg(
QDir::toNativeSeparators(tempOutFile)).toLocal8Bit() + "\r\n";
saver.write(redirect);
saver.write("@echo " + marker);
saver.write("set\r\n");
saver.write("@echo " + marker);
if (!saver.finalize()) {
qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString()));
return false;
@@ -304,19 +297,31 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
return false;
}
// The SDK/MSVC scripts do not return exit codes != 0. Check on stdout.
const QByteArray stdOut = run.readAllStandardOutput();
QByteArray stdOut = run.readAllStandardOutput();
if (!stdOut.isEmpty() && (stdOut.contains("Unknown") || stdOut.contains("Error")))
qWarning("%s: '%s' reports:\n%s", Q_FUNC_INFO, call.constData(), stdOut.constData());
//
// Now parse the file to get the environment settings
QFile varsFile(tempOutFile);
if (!varsFile.open(QIODevice::ReadOnly))
int start = stdOut.indexOf(marker);
if (start == -1) {
qWarning("Could not find start marker in stdout output.");
return false;
}
stdOut = stdOut.mid(start + marker.size());
int end = stdOut.indexOf(marker);
if (end == -1) {
qWarning("Could not find end marker in stdout output.");
return false;
}
stdOut = stdOut.left(end);
QStringList lines = QString::fromLocal8Bit(stdOut).split(QLatin1String("\r\n"));
QRegExp regexp(QLatin1String("(\\w*)=(.*)"));
while (!varsFile.atEnd()) {
const QString line = QString::fromLocal8Bit(varsFile.readLine()).trimmed();
foreach (const QString &line, lines) {
if (regexp.exactMatch(line)) {
const QString varName = regexp.cap(1);
const QString varValue = regexp.cap(2);
@@ -326,10 +331,6 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env,
}
}
// Tidy up and remove the file
varsFile.close();
varsFile.remove();
return true;
}

View File

@@ -990,6 +990,20 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFileNo
m_qmakeGlobals->setCommandLineArguments(m_rootProjectNode->buildDir(), qmakeArgs);
QtSupport::ProFileCacheManager::instance()->incRefCount();
// On ios, qmake is called recursively, and the second call with a different
// spec.
// macx-ios-clang just creates supporting makefiles, and to avoid being
// slow does not evaluate everything, and contains misleading information
// (that is never used).
// macx-xcode correctly evaluates the variables and generates the xcodeproject
// that is actually used to build the application.
//
// It is important to override the spec file only for the creator evaluator,
// and not the qmake buildstep used to build the app (as we use the makefiles).
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios"; // from Ios::Constants
if (qtVersion->type() == QLatin1String(IOSQT))
m_qmakeGlobals->xqmakespec = QLatin1String("macx-xcode");
}
++m_qmakeGlobalsRefCnt;

View File

@@ -70,7 +70,12 @@ Rectangle {
mainviewTimePerPixel = Math.abs(endTime - startTime) / root.width;
backgroundMarks.updateMarks(startTime, endTime);
view.updateFlickRange(startTime, endTime);
view.startTime = startTime;
view.endTime = endTime;
view.updateWindow();
}
onWindowChanged: {
view.updateWindow();
}
}
@@ -250,7 +255,7 @@ Rectangle {
onWidthChanged: {
var duration = Math.abs(zoomControl.endTime() - zoomControl.startTime());
if (duration > 0)
contentWidth = qmlProfilerModelProxy.traceDuration() * width / duration;
contentWidth = zoomControl.windowLength() * width / duration;
}
// ***** child items
@@ -293,33 +298,29 @@ Rectangle {
return;
var newStartTime = Math.round(flick.contentX * (endTime - startTime) / flick.width) +
qmlProfilerModelProxy.traceStartTime();
zoomControl.windowStart();
if (Math.abs(newStartTime - startTime) > 1) {
var newEndTime = Math.round((flick.contentX + flick.width) *
(endTime - startTime) /
flick.width) +
qmlProfilerModelProxy.traceStartTime();
flick.width) + zoomControl.windowStart();
zoomControl.setRange(newStartTime, newEndTime);
}
}
function updateFlickRange(start, end) {
var duration = end - start;
if (recursionGuard || duration <= 0 || (start === startTime && end === endTime))
function updateWindow() {
var duration = zoomControl.duration();
if (recursionGuard || duration <= 0)
return;
recursionGuard = true;
startTime = start;
endTime = end;
if (!flick.flickingHorizontally) {
if (!flick.movingHorizontally) {
// This triggers an unwanted automatic change in contentX. We ignore that by
// checking recursionGuard in this function and in updateZoomControl.
flick.contentWidth = qmlProfilerModelProxy.traceDuration() * flick.width /
duration;
flick.contentWidth = zoomControl.windowLength() * flick.width / duration;
var newStartX = (startTime - qmlProfilerModelProxy.traceStartTime()) *
flick.width / duration;
var newStartX = (startTime - zoomControl.windowStart()) * flick.width /
duration;
if (isFinite(newStartX) && Math.abs(newStartX - flick.contentX) >= 1)
flick.contentX = newStartX;
@@ -418,7 +419,9 @@ Rectangle {
function updateZoomLevel() {
zoomSlider.externalUpdate = true;
zoomSlider.value = Math.pow((view.endTime - view.startTime) / qmlProfilerModelProxy.traceDuration(), 1 / zoomSlider.exponent) * zoomSlider.maximumValue;
zoomSlider.value = Math.pow((view.endTime - view.startTime) /
zoomControl.windowLength(),
1 / zoomSlider.exponent) * zoomSlider.maximumValue;
}
@@ -434,7 +437,7 @@ Rectangle {
property int minWindowLength: 1e5 // 0.1 ms
onValueChanged: {
if (externalUpdate || qmlProfilerModelProxy.traceEndTime() <= qmlProfilerModelProxy.traceStartTime()) {
if (externalUpdate || zoomControl.windowEnd() <= zoomControl.windowStart()) {
// Zoom range is independently updated. We shouldn't mess
// with it here as otherwise we might introduce rounding
// or arithmetic errors.
@@ -443,7 +446,7 @@ Rectangle {
}
var windowLength = Math.max(
Math.pow(value / maximumValue, exponent) * qmlProfilerModelProxy.traceDuration(),
Math.pow(value / maximumValue, exponent) * zoomControl.windowLength(),
minWindowLength);
var fixedPoint = (view.startTime + view.endTime) / 2;
@@ -454,7 +457,7 @@ Rectangle {
fixedPoint = newFixedPoint;
}
var startTime = Math.max(qmlProfilerModelProxy.traceStartTime(), fixedPoint - windowLength / 2)
var startTime = Math.max(zoomControl.windowStart(), fixedPoint - windowLength / 2)
zoomControl.setRange(startTime, startTime + windowLength);
}
}

View File

@@ -38,7 +38,7 @@ RangeMover {
property string endTimeString: detailedPrintTime(startTime+duration)
property string durationString: detailedPrintTime(duration)
property double startTime: getLeft() * viewTimePerPixel + qmlProfilerModelProxy.traceStartTime()
property double startTime: getLeft() * viewTimePerPixel + zoomControl.windowStart()
property double duration: Math.max(getWidth() * viewTimePerPixel, 500)
property double viewTimePerPixel: 1
property double creationReference : 0

View File

@@ -112,18 +112,24 @@ qint64 QmlProfilerTraceTime::duration() const
void QmlProfilerTraceTime::clear()
{
m_startTime = -1;
m_endTime = -1;
setStartTime(-1);
setEndTime(-1);
}
void QmlProfilerTraceTime::setStartTime(qint64 time)
{
m_startTime = time;
if (time != m_startTime) {
m_startTime = time;
emit startTimeChanged(time);
}
}
void QmlProfilerTraceTime::setEndTime(qint64 time)
{
m_endTime = time;
if (time != m_endTime) {
m_endTime = time;
emit endTimeChanged(time);
}
}

View File

@@ -84,6 +84,10 @@ public:
qint64 endTime() const;
qint64 duration() const;
signals:
void startTimeChanged(qint64);
void endTimeChanged(qint64);
public slots:
void clear();
void setStartTime(qint64 time);

View File

@@ -61,15 +61,88 @@ namespace QmlProfiler {
namespace Internal {
/////////////////////////////////////////////////////////
ZoomControl::ZoomControl(const QmlProfilerTraceTime *traceTime, QObject *parent) :
QObject(parent), m_startTime(traceTime->startTime()), m_endTime(traceTime->endTime()),
m_windowStart(traceTime->startTime()), m_windowEnd(traceTime->endTime()),
m_traceTime(traceTime), m_windowLocked(false)
{
connect(traceTime, SIGNAL(startTimeChanged(qint64)), this, SLOT(rebuildWindow()));
connect(traceTime, SIGNAL(endTimeChanged(qint64)), this, SLOT(rebuildWindow()));
connect(&m_timer, SIGNAL(timeout()), this, SLOT(moveWindow()));
}
void ZoomControl::setRange(qint64 startTime, qint64 endTime)
{
if (m_startTime != startTime || m_endTime != endTime) {
m_timer.stop();
m_startTime = startTime;
m_endTime = endTime;
rebuildWindow();
emit rangeChanged();
}
}
void ZoomControl::rebuildWindow()
{
qint64 minDuration = 1; // qMax needs equal data types, so literal 1 won't do
qint64 shownDuration = qMax(duration(), minDuration);
qint64 oldWindowStart = m_windowStart;
qint64 oldWindowEnd = m_windowEnd;
if (m_traceTime->duration() / shownDuration < MAX_ZOOM_FACTOR) {
m_windowStart = m_traceTime->startTime();
m_windowEnd = m_traceTime->endTime();
} else if (windowLength() / shownDuration > MAX_ZOOM_FACTOR ||
windowLength() / shownDuration * 2 < MAX_ZOOM_FACTOR) {
qint64 keep = shownDuration * MAX_ZOOM_FACTOR / 2 - shownDuration;
m_windowStart = m_startTime - keep;
if (m_windowStart < m_traceTime->startTime()) {
keep += m_traceTime->startTime() - m_windowStart;
m_windowStart = m_traceTime->startTime();
}
m_windowEnd = m_endTime + keep;
if (m_windowEnd > m_traceTime->endTime()) {
m_windowStart = qMax(m_traceTime->startTime(),
m_windowStart - m_windowEnd - m_traceTime->endTime());
m_windowEnd = m_traceTime->endTime();
}
} else {
m_timer.start(500);
}
if (oldWindowStart != m_windowStart || oldWindowEnd != m_windowEnd)
emit windowChanged();
}
void ZoomControl::moveWindow()
{
if (m_windowLocked)
return;
m_timer.stop();
qint64 offset = (m_endTime - m_windowEnd + m_startTime - m_windowStart) / 2;
if (offset == 0 || (offset < 0 && m_windowStart == m_traceTime->startTime()) ||
(offset > 0 && m_windowEnd == m_traceTime->endTime())) {
return;
} else if (offset > duration()) {
offset = (offset + duration()) / 2;
} else if (offset < -duration()) {
offset = (offset - duration()) / 2;
}
m_windowStart += offset;
if (m_windowStart < m_traceTime->startTime()) {
m_windowEnd += m_traceTime->startTime() - m_windowStart;
m_windowStart = m_traceTime->startTime();
}
m_windowEnd += offset;
if (m_windowEnd > m_traceTime->endTime()) {
m_windowStart -= m_windowEnd - m_traceTime->endTime();
m_windowEnd = m_traceTime->endTime();
}
emit windowChanged();
m_timer.start(100);
}
/////////////////////////////////////////////////////////
class QmlProfilerTraceView::QmlProfilerTraceViewPrivate
{
@@ -108,7 +181,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT
{
setObjectName(QLatin1String("QML Profiler"));
d->m_zoomControl = new ZoomControl(this);
d->m_zoomControl = new ZoomControl(modelManager->traceTime(), this);
connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange()));
QVBoxLayout *groupLayout = new QVBoxLayout;
@@ -396,6 +469,18 @@ void QmlProfilerTraceView::resizeEvent(QResizeEvent *event)
emit resized();
}
void QmlProfilerTraceView::mousePressEvent(QMouseEvent *event)
{
d->m_zoomControl->setWindowLocked(true);
QWidget::mousePressEvent(event);
}
void QmlProfilerTraceView::mouseReleaseEvent(QMouseEvent *event)
{
d->m_zoomControl->setWindowLocked(false);
QWidget::mouseReleaseEvent(event);
}
////////////////////////////////////////////////////////////////
// Context menu
void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev)

View File

@@ -30,8 +30,10 @@
#ifndef QMLPROFILERTRACEVIEW_H
#define QMLPROFILERTRACEVIEW_H
#include "qmlprofilermodelmanager.h"
#include <QQuickView>
#include <QWidget>
#include <QTimer>
namespace Analyzer { class IAnalyzerTool; }
@@ -47,19 +49,38 @@ class QmlProfilerViewManager;
class ZoomControl : public QObject {
Q_OBJECT
public:
ZoomControl(QObject *parent=0):QObject(parent),m_startTime(0),m_endTime(0) {}
static const qint64 MAX_ZOOM_FACTOR = 1 << 12;
ZoomControl(const QmlProfilerTraceTime *traceTime, QObject *parent = 0);
~ZoomControl(){}
Q_INVOKABLE void setRange(qint64 startTime, qint64 endTime);
Q_INVOKABLE qint64 startTime() { return m_startTime; }
Q_INVOKABLE qint64 endTime() { return m_endTime; }
Q_INVOKABLE qint64 startTime() const { return m_startTime; }
Q_INVOKABLE qint64 endTime() const { return m_endTime; }
Q_INVOKABLE qint64 duration() const { return m_endTime - m_startTime; }
Q_INVOKABLE qint64 windowStart() const { return m_windowStart; }
Q_INVOKABLE qint64 windowEnd() const { return m_windowEnd; }
Q_INVOKABLE qint64 windowLength() const { return m_windowEnd - m_windowStart; }
void setWindowLocked(bool lock) { m_windowLocked = lock; }
signals:
void rangeChanged();
void windowChanged();
private slots:
void rebuildWindow();
void moveWindow();
private:
qint64 m_startTime;
qint64 m_endTime;
qint64 m_windowStart;
qint64 m_windowEnd;
const QmlProfilerTraceTime *m_traceTime;
QTimer m_timer;
bool m_windowLocked;
};
class QmlProfilerTraceView : public QWidget
@@ -97,6 +118,8 @@ private slots:
protected:
virtual void resizeEvent(QResizeEvent *event);
virtual void contextMenuEvent(QContextMenuEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
private slots:
void setZoomSliderEnabled(bool enabled);

View File

@@ -54,6 +54,7 @@ static bool debugExamples()
}
static const char kSelectedExampleSetKey[] = "WelcomePage/SelectedExampleSet";
static const char kExamplesSearchStringKey[] = "WelcomePage/ExamplesSearchString";
void ExampleSetModel::writeCurrentIdToSettings(int currentIndex) const
{
@@ -841,6 +842,16 @@ void ExamplesListModelFilter::filterForExampleSet(int index)
m_sourceModel->selectExampleSet(index);
}
void ExamplesListModelFilter::writeSearchStringToSettings(const QString &string)
{
Core::ICore::settings()->setValue(QLatin1String(kExamplesSearchStringKey), string);
}
QString ExamplesListModelFilter::readSearchStringsFromSettings()
{
return Core::ICore::settings()->value(QLatin1String(kExamplesSearchStringKey)).toString();
}
void ExamplesListModelFilter::setShowTutorialsOnly(bool showTutorialsOnly)
{
m_showTutorialsOnly = showTutorialsOnly;

View File

@@ -185,6 +185,8 @@ public:
QAbstractItemModel* exampleSetModel();
Q_INVOKABLE void filterForExampleSet(int index);
Q_INVOKABLE void writeSearchStringToSettings(const QString &string);
Q_INVOKABLE QString readSearchStringsFromSettings();
public slots:
void setFilterTags(const QStringList &arg)

View File

@@ -35,8 +35,14 @@
#include <projectexplorer/target.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/deployablefile.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/qtcprocess.h>
#include <QRegularExpression>
using namespace ProjectExplorer;
using Utils::QtcProcess;
@@ -45,6 +51,7 @@ namespace Internal {
WinRtPackageDeploymentStep::WinRtPackageDeploymentStep(BuildStepList *bsl)
: AbstractProcessStep(bsl, Constants::WINRT_BUILD_STEP_DEPLOY)
, m_createMappingFile(false)
{
setDisplayName(tr("Run windeployqt"));
m_args = defaultWinDeployQtArguments();
@@ -56,11 +63,46 @@ bool WinRtPackageDeploymentStep::init()
const QString targetPath
= target()->applicationTargets().targetForProject(proFile).toString()
+ QLatin1String(".exe");
QString targetDir = targetPath.left(targetPath.lastIndexOf(QLatin1Char('/')) + 1);
// ### Actually, targetForProject is supposed to return the file path including the file
// extension. Whenever this will eventually work, we have to remove the .exe suffix here.
const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
if (!qt)
return false;
m_isWinPhone = (qt->type() == QLatin1String(Constants::WINRT_WINPHONEQT));
QString args = QtcProcess::quoteArg(QDir::toNativeSeparators(targetPath));
args += QLatin1Char(' ') + m_args;
if (m_isWinPhone) {
m_manifestFileName = QLatin1String("WMAppManifest");
m_createMappingFile = true;
} else {
m_manifestFileName = QLatin1String("AppxManifest");
}
if (m_createMappingFile) {
args += QLatin1String(" -list mapping");
m_mappingFileContent = QLatin1String("[Files]\n\"") + QDir::toNativeSeparators(targetDir)
+ m_manifestFileName + QLatin1String(".xml\" \"") + m_manifestFileName + QLatin1String(".xml\"\n");
QDir assetDirectory(targetDir + QLatin1String("assets"));
if (assetDirectory.exists()) {
QStringList iconsToDeploy;
const QString fullManifestPath = targetDir + m_manifestFileName + QLatin1String(".xml");
if (!parseIconsAndExecutableFromManifest(fullManifestPath, &iconsToDeploy,
&m_executablePathInManifest)) {
raiseError(tr("Cannot parse manifest file %1.").arg(fullManifestPath));
return false;
}
foreach (QString icon, iconsToDeploy) {
m_mappingFileContent += QLatin1Char('"')
+ QDir::toNativeSeparators(targetDir + icon) + QLatin1String("\" \"")
+ QDir::toNativeSeparators(icon) + QLatin1String("\"\n");
}
}
}
ProcessParameters *params = processParameters();
params->setCommand(QLatin1String("windeployqt.exe"));
@@ -70,6 +112,67 @@ bool WinRtPackageDeploymentStep::init()
return AbstractProcessStep::init();
}
bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
{
if (m_createMappingFile) {
Utils::FileName proFile = Utils::FileName::fromString(project()->projectFilePath());
QString targetPath
= target()->applicationTargets().targetForProject(proFile).toString();
QString targetDir = targetPath.left(targetPath.lastIndexOf(QLatin1Char('/')) + 1);
QString targetInstallationPath;
// The list holds the local file paths and the "remote" file paths
QList<QPair<QString, QString> > installableFilesList;
foreach (DeployableFile file, target()->deploymentData().allFiles()) {
QString remoteFilePath = file.remoteFilePath();
QString localFilePath = file.localFilePath().toString();
if (localFilePath == targetPath) {
if (!targetPath.endsWith(QLatin1String(".exe"))) {
remoteFilePath += QLatin1String(".exe");
localFilePath += QLatin1String(".exe");
}
targetInstallationPath = remoteFilePath;
}
installableFilesList.append(QPair<QString, QString>(localFilePath, remoteFilePath));
}
// if there are no INSTALLS set we just deploy the files from windeployqt, the manifest
// and the icons referenced in there and the actual build target
if (targetInstallationPath.isEmpty()) {
targetPath += QLatin1String(".exe");
m_mappingFileContent
+= QLatin1Char('"') + QDir::toNativeSeparators(targetPath) + QLatin1String("\" \"")
+ QDir::toNativeSeparators(m_executablePathInManifest) + QLatin1String("\"\n");
} else {
targetInstallationPath = targetInstallationPath.left(targetInstallationPath.lastIndexOf(QLatin1Char('/')) + 1);
for (int i = 0; i < installableFilesList.length(); ++i) {
QPair<QString, QString> pair = installableFilesList.at(i);
// For the mapping file we need the remote paths relative to the application's executable
const QString relativeRemotePath = QDir(targetInstallationPath).relativeFilePath(pair.second);
m_mappingFileContent += QLatin1Char('"') + QDir::toNativeSeparators(pair.first)
+ QLatin1String("\" \"") + QDir::toNativeSeparators(relativeRemotePath)
+ QLatin1String("\"\n");
}
}
const QString mappingFilePath = targetDir + m_manifestFileName + QLatin1String(".map");
QFile mappingFile(mappingFilePath);
if (!mappingFile.open(QFile::WriteOnly | QFile::Text)) {
raiseError(tr("Cannot open mapping file %1 for writing.").arg(mappingFilePath));
return false;
}
mappingFile.write(m_mappingFileContent.toUtf8());
}
return AbstractProcessStep::processSucceeded(exitCode, status);
}
void WinRtPackageDeploymentStep::stdOutput(const QString &line)
{
if (m_createMappingFile)
m_mappingFileContent += line;
AbstractProcessStep::stdOutput(line);
}
BuildStepConfigWidget *WinRtPackageDeploymentStep::createConfigWidget()
{
return new WinRtPackageDeploymentStepWidget(this);
@@ -93,6 +196,13 @@ QString WinRtPackageDeploymentStep::defaultWinDeployQtArguments() const
return args;
}
void WinRtPackageDeploymentStep::raiseError(const QString &errorMessage)
{
emit addOutput(errorMessage, BuildStep::ErrorMessageOutput);
emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, errorMessage, Utils::FileName(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT));
}
bool WinRtPackageDeploymentStep::fromMap(const QVariantMap &map)
{
if (!AbstractProcessStep::fromMap(map))
@@ -110,5 +220,31 @@ QVariantMap WinRtPackageDeploymentStep::toMap() const
return map;
}
bool WinRtPackageDeploymentStep::parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *icons, QString *executable)
{
if (!icons->isEmpty())
icons->clear();
QFile manifestFile(manifestFileName);
if (!manifestFile.open(QFile::ReadOnly))
return false;
const QString contents = QString::fromUtf8(manifestFile.readAll());
QRegularExpression iconPattern(QStringLiteral("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)"));
QRegularExpressionMatchIterator iterator = iconPattern.globalMatch(contents);
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
const QString icon = match.captured(0);
icons->append(icon);
}
QRegularExpression executablePattern(QStringLiteral("ImagePath=\"([a-zA-Z0-9_-]*\\.exe)\""));
QRegularExpressionMatch match = executablePattern.match(contents);
if (!match.hasMatch())
return false;
*executable = match.captured(1);
return true;
}
} // namespace Internal
} // namespace WinRt

View File

@@ -41,17 +41,28 @@ class WinRtPackageDeploymentStep : public ProjectExplorer::AbstractProcessStep
public:
explicit WinRtPackageDeploymentStep(ProjectExplorer::BuildStepList *bsl);
bool init();
bool processSucceeded(int exitCode, QProcess::ExitStatus status);
void stdOutput(const QString &line);
ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
void setWinDeployQtArguments(const QString &args);
QString winDeployQtArguments() const;
QString defaultWinDeployQtArguments() const;
void raiseError(const QString &errorMessage);
bool fromMap(const QVariantMap &map);
QVariantMap toMap() const;
private:
bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable);
QString m_args;
QString m_executablePathInManifest;
QString m_mappingFileContent;
QString m_manifestFileName;
bool m_isWinPhone;
bool m_createMappingFile;
};
} // namespace Internal

View File

@@ -100,7 +100,8 @@ QString ProFileEvaluator::sysrootify(const QString &path, const QString &baseDir
#endif
const bool isHostSystemPath =
option->sysroot.isEmpty() || path.startsWith(option->sysroot, cs)
|| path.startsWith(baseDir, cs) || path.startsWith(d->m_outputDir, cs);
|| path.startsWith(baseDir, cs) || path.startsWith(d->m_outputDir, cs)
|| !QFileInfo(option->sysroot + path).exists();
return isHostSystemPath ? path : option->sysroot + path;
}

View File

@@ -79,7 +79,7 @@ def main():
if not startedWithoutPluginError():
return
# open example project
openQmakeProject(examplePath)
openQmakeProject(examplePath, Targets.DESKTOP_480_GCC)
# open qml file
openDocument("propertyanimation.QML.qml.color-animation\\.qml")
# get editor

View File

@@ -43,7 +43,7 @@ def main():
addHelpDocumentation([os.path.join(sdkPath, "Documentation", "qt.qch")])
templateDir = prepareTemplate(sourceExample)
installLazySignalHandler("{type='Core::FutureProgress' unnamed='1'}", "finished()", "__handleFutureProgress__")
openQmakeProject(os.path.join(templateDir,proFile))
openQmakeProject(os.path.join(templateDir,proFile), Targets.DESKTOP_480_GCC)
openDocument("focus.QML.qml.focus\\.qml")
testRenameId()
testFindUsages()

View File

@@ -42,7 +42,7 @@ def main():
test.verify(waitFor("sessionName in str(mainWindow.windowTitle)", 2000),
"Verifying window title contains created session name.")
for project in projects:
openQmakeProject(project)
openQmakeProject(project, Targets.DESKTOP_480_GCC)
progressBarWait(20000)
checkNavigator(68, "Verifying whether all projects have been opened.")
openDocument("propertyanimation.QML.qml.color-animation\\.qml")

View File

@@ -42,11 +42,7 @@ def main():
startApplication("qtcreator" + SettingsPath)
if not startedWithoutPluginError():
return
targets = openQmakeProject(os.path.join(templateDir, proFile))
# make sure we use the 474 kit for having QtQuick 1.0 support
switchViewTo(ViewConstants.PROJECTS)
switchToBuildOrRunSettingsFor(len(targets), 0, ProjectSettings.BUILD)
switchViewTo(ViewConstants.EDIT)
openQmakeProject(os.path.join(templateDir, proFile), Targets.DESKTOP_480_GCC)
qmlFiles = ["focus.QML.qml.focus\\.qml", "focus.QML.qml.Core.ListMenu\\.qml"]
checkOutlineFor(qmlFiles)
testModify()