forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.6'
Conflicts: src/plugins/android/androiddeployqtstep.cpp src/plugins/cmakeprojectmanager/cmakerunconfiguration.cpp src/plugins/qmakeprojectmanager/wizards/testwizard.cpp src/plugins/qtsupport/exampleslistmodel.cpp src/plugins/qtsupport/gettingstartedwelcomepage.cpp Change-Id: I126823f5f60613509520c07f52be7bc9d4f4367c
This commit is contained in:
21
dist/changes-4.6.0.md
vendored
21
dist/changes-4.6.0.md
vendored
@@ -24,8 +24,18 @@ General
|
|||||||
Editing
|
Editing
|
||||||
|
|
||||||
* Added option to display annotations between lines (QTCREATORBUG-19181)
|
* Added option to display annotations between lines (QTCREATORBUG-19181)
|
||||||
|
* Added shortcut setting for jumping to document start and end
|
||||||
* Fixed that editor could jump to end of file when editing in a different split
|
* Fixed that editor could jump to end of file when editing in a different split
|
||||||
(QTCREATORBUG-19550)
|
(QTCREATORBUG-19550)
|
||||||
|
* Fixed order of items in list of recent documents when documents are suspended
|
||||||
|
(QTCREATORBUG-19758)
|
||||||
|
* Fixed crash in generic highlighter (QTCREATORBUG-19916)
|
||||||
|
* Fixed issue with snippet variables on Gnome (QTCREATORBUG-19571)
|
||||||
|
* Fixed tool tips in binary editor (QTCREATORBUG-17573)
|
||||||
|
|
||||||
|
Help
|
||||||
|
|
||||||
|
* Improved startup performance
|
||||||
|
|
||||||
All Projects
|
All Projects
|
||||||
|
|
||||||
@@ -54,12 +64,17 @@ QML Support
|
|||||||
Debugging
|
Debugging
|
||||||
|
|
||||||
* Split `Expressions` view from `Locals` view (QTCREATORBUG-19167)
|
* Split `Expressions` view from `Locals` view (QTCREATORBUG-19167)
|
||||||
|
* LLDB
|
||||||
|
* Fixed attaching to core file (QTCREATORBUG-18722)
|
||||||
|
* Fixed issue when killing LLDB from the outside (QTCREATORBUG-18723)
|
||||||
|
|
||||||
Qt Quick Designer
|
Qt Quick Designer
|
||||||
|
|
||||||
* Added font and text properties from Qt 5.10
|
* Added font and text properties from Qt 5.10
|
||||||
* Fixed that items blurred when zooming in
|
* Fixed that items blurred when zooming in
|
||||||
* Fixed crash when changing control focus policy (QTCREATORBUG-19563)
|
* Fixed crash when changing control focus policy (QTCREATORBUG-19563)
|
||||||
|
* Fixed assert in backend process with Qt 5.9.4 & 5.10.1 and later
|
||||||
|
(QTCREATORBUG-19729)
|
||||||
|
|
||||||
Version Control Systems
|
Version Control Systems
|
||||||
|
|
||||||
@@ -73,15 +88,18 @@ Version Control Systems
|
|||||||
Diff Viewer
|
Diff Viewer
|
||||||
|
|
||||||
* Added folding for files and chunks
|
* Added folding for files and chunks
|
||||||
|
* Fixed issue with repeated stage and unstage operation
|
||||||
|
|
||||||
Test Integration
|
Test Integration
|
||||||
|
|
||||||
* Added grouping of test cases (QTCREATORBUG-17979)
|
* Added grouping of test cases (QTCREATORBUG-17979)
|
||||||
|
* Fixed handling of `qCritical` output (QTCREATORBUG-19795)
|
||||||
* Google Test
|
* Google Test
|
||||||
* Fixed detection of crashed tests (QTCREATORBUG-19565)
|
* Fixed detection of crashed tests (QTCREATORBUG-19565)
|
||||||
|
|
||||||
Model Editor
|
Model Editor
|
||||||
|
|
||||||
|
* Removed experimental state
|
||||||
* Added support for text alignment
|
* Added support for text alignment
|
||||||
* Added support for multi-line object names
|
* Added support for multi-line object names
|
||||||
* Added support for dragging items onto model editor from more panes
|
* Added support for dragging items onto model editor from more panes
|
||||||
@@ -89,6 +107,8 @@ Model Editor
|
|||||||
* Added `Flat` visual role
|
* Added `Flat` visual role
|
||||||
* Added `Add Related Elements` to diagram context menu
|
* Added `Add Related Elements` to diagram context menu
|
||||||
* Added wizard for scratch models
|
* Added wizard for scratch models
|
||||||
|
* Moved export actions to `File` menu
|
||||||
|
* Moved zoom actions to editor tool bar
|
||||||
* Fixed issue with selecting items (QTCREATORBUG-18368)
|
* Fixed issue with selecting items (QTCREATORBUG-18368)
|
||||||
|
|
||||||
Platform Specific
|
Platform Specific
|
||||||
@@ -98,6 +118,7 @@ Windows
|
|||||||
* Added support for the [heob](https://github.com/ssbssa/heob/releases)
|
* Added support for the [heob](https://github.com/ssbssa/heob/releases)
|
||||||
memory analyzer
|
memory analyzer
|
||||||
* Fixed detection of CDB in non-default installation roots
|
* Fixed detection of CDB in non-default installation roots
|
||||||
|
* Fixed issue with setting `PATH` versus `Path` environment variable
|
||||||
|
|
||||||
Android
|
Android
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -155,14 +155,20 @@ Item {
|
|||||||
property int minimumWidth: {
|
property int minimumWidth: {
|
||||||
// max(width of longest label * 2, minimumInnerWidth)
|
// max(width of longest label * 2, minimumInnerWidth)
|
||||||
var result = minimumInnerWidth;
|
var result = minimumInnerWidth;
|
||||||
for (var i = 0; i < children.length; i += 2)
|
for (var i = 0; i < children.length; ++i) {
|
||||||
result = Math.max(children[i].implicitWidth * 2 + innerMargin, result);
|
if (children[i].isLabel)
|
||||||
|
result = Math.max(children[i].implicitWidth * 2 + innerMargin, result);
|
||||||
|
}
|
||||||
|
|
||||||
return result + 2 * outerMargin;
|
return result + 2 * outerMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property int labelWidth: (minimumWidth - innerMargin) / 2 - outerMargin
|
||||||
|
property int valueWidth: dragHandle.x - labelWidth - innerMargin - outerMargin
|
||||||
|
|
||||||
onMinimumWidthChanged: {
|
onMinimumWidthChanged: {
|
||||||
if (dragHandle.x < minimumWidth)
|
if (dragHandle.x < minimumWidth - outerMargin)
|
||||||
dragHandle.x = minimumWidth;
|
dragHandle.x = minimumWidth - outerMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
@@ -171,8 +177,7 @@ Item {
|
|||||||
property bool isLabel: index % 2 === 0
|
property bool isLabel: index % 2 === 0
|
||||||
font.bold: isLabel
|
font.bold: isLabel
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
width: (text === "" || isLabel)
|
width: isLabel ? col.labelWidth : col.valueWidth
|
||||||
? implicitWidth : (dragHandle.x - col.minimumWidth / 2 - innerMargin)
|
|
||||||
text: isLabel ? (modelData + ":") : modelData
|
text: isLabel ? (modelData + ":") : modelData
|
||||||
color: contentTextColor
|
color: contentTextColor
|
||||||
}
|
}
|
||||||
@@ -213,7 +218,7 @@ Item {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
drag.target: parent
|
drag.target: parent
|
||||||
drag.minimumX: col.minimumWidth
|
drag.minimumX: col.minimumWidth - outerMargin
|
||||||
drag.axis: Drag.XAxis
|
drag.axis: Drag.XAxis
|
||||||
cursorShape: Qt.SizeHorCursor
|
cursorShape: Qt.SizeHorCursor
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,8 @@ import QtQuick 2.1
|
|||||||
TimelineText {
|
TimelineText {
|
||||||
property bool isLabel: false
|
property bool isLabel: false
|
||||||
property int valueWidth: 170
|
property int valueWidth: 170
|
||||||
|
property int labelWidth: implicitWidth
|
||||||
font.bold: isLabel
|
font.bold: isLabel
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
width: text === "" ? 0 : (isLabel ? implicitWidth : valueWidth)
|
width: text === "" ? 0 : (isLabel ? labelWidth : valueWidth)
|
||||||
}
|
}
|
||||||
|
@@ -173,27 +173,35 @@ Item {
|
|||||||
|
|
||||||
//details
|
//details
|
||||||
Grid {
|
Grid {
|
||||||
|
property int outerMargin: 10
|
||||||
|
property int minimumWidth: 150
|
||||||
|
property int labelWidth: (minimumWidth - spacing) / 2 - outerMargin
|
||||||
|
property int valueWidth: dragHandle.x - labelWidth - spacing - outerMargin
|
||||||
|
|
||||||
id: col
|
id: col
|
||||||
x: 10
|
x: outerMargin
|
||||||
y: 5
|
y: 5
|
||||||
spacing: 5
|
spacing: 5
|
||||||
columns: 2
|
columns: 2
|
||||||
property int minimumWidth: 150
|
|
||||||
|
|
||||||
onChildrenChanged: {
|
onChildrenChanged: {
|
||||||
// max(width of longest label * 2, 150)
|
// max(width of longest label * 2, 150)
|
||||||
var result = 150;
|
var result = 150;
|
||||||
for (var i = 0; i < children.length; i += 2)
|
for (var i = 0; i < children.length; ++i) {
|
||||||
result = Math.max(children[i].implicitWidth * 2 + spacing, result);
|
if (children[i].isLabel)
|
||||||
minimumWidth = result + 20;
|
result = Math.max(children[i].implicitWidth * 2 + spacing, result);
|
||||||
if (dragHandle.x < minimumWidth)
|
}
|
||||||
dragHandle.x = minimumWidth;
|
|
||||||
|
minimumWidth = result + 2 * outerMargin;
|
||||||
|
if (dragHandle.x < minimumWidth - outerMargin)
|
||||||
|
dragHandle.x = minimumWidth - outerMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: eventInfo.ready ? eventInfo : 0
|
model: eventInfo.ready ? eventInfo : 0
|
||||||
Detail {
|
Detail {
|
||||||
valueWidth: (dragHandle.x - col.minimumWidth / 2 - col.spacing)
|
labelWidth: col.labelWidth
|
||||||
|
valueWidth: col.valueWidth
|
||||||
isLabel: index % 2 === 0
|
isLabel: index % 2 === 0
|
||||||
text: (content === undefined) ? "" : (isLabel ? (content + ":") : content)
|
text: (content === undefined) ? "" : (isLabel ? (content + ":") : content)
|
||||||
}
|
}
|
||||||
@@ -285,7 +293,7 @@ Item {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
drag.target: parent
|
drag.target: parent
|
||||||
drag.minimumX: col.minimumWidth
|
drag.minimumX: col.minimumWidth - col.outerMargin
|
||||||
drag.axis: Drag.XAxis
|
drag.axis: Drag.XAxis
|
||||||
cursorShape: Qt.SizeHorCursor
|
cursorShape: Qt.SizeHorCursor
|
||||||
}
|
}
|
||||||
|
@@ -137,25 +137,34 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
|
|||||||
m_avdName = info.avdname;
|
m_avdName = info.avdname;
|
||||||
m_serialNumber = info.serialNumber;
|
m_serialNumber = info.serialNumber;
|
||||||
|
|
||||||
m_appProcessBinaries.clear();
|
ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
|
||||||
m_libdir = QLatin1String("lib");
|
m_filesToPull.clear();
|
||||||
|
QString buildDir = bc ? bc->buildDirectory().toString() : QString();
|
||||||
|
if (bc && !buildDir.endsWith("/")) {
|
||||||
|
buildDir += "/";
|
||||||
|
}
|
||||||
|
QString linkerName("linker");
|
||||||
|
QString libDirName("lib");
|
||||||
if (info.cpuAbi.contains(QLatin1String("arm64-v8a")) ||
|
if (info.cpuAbi.contains(QLatin1String("arm64-v8a")) ||
|
||||||
info.cpuAbi.contains(QLatin1String("x86_64"))) {
|
info.cpuAbi.contains(QLatin1String("x86_64"))) {
|
||||||
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||||
if (tc && tc->targetAbi().wordWidth() == 64) {
|
if (tc && tc->targetAbi().wordWidth() == 64) {
|
||||||
m_appProcessBinaries << QLatin1String("/system/bin/app_process64");
|
m_filesToPull["/system/bin/app_process64"] = buildDir + "app_process";
|
||||||
m_libdir += QLatin1String("64");
|
libDirName = "lib64";
|
||||||
|
linkerName = "linker64";
|
||||||
} else {
|
} else {
|
||||||
m_appProcessBinaries << QLatin1String("/system/bin/app_process32");
|
m_filesToPull["/system/bin/app_process32"] = buildDir + "app_process";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_appProcessBinaries << QLatin1String("/system/bin/app_process32")
|
m_appProcessBinaries << QLatin1String("/system/bin/app_process32")
|
||||||
<< QLatin1String("/system/bin/app_process");
|
<< QLatin1String("/system/bin/app_process");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_filesToPull["/system/bin/" + linkerName] = buildDir + linkerName;
|
||||||
|
m_filesToPull["/system/" + libDirName + "/libc.so"] = buildDir + "libc.so";
|
||||||
|
|
||||||
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
|
AndroidManager::setDeviceSerialNumber(target(), m_serialNumber);
|
||||||
|
|
||||||
ProjectExplorer::BuildConfiguration *bc = target()->activeBuildConfiguration();
|
|
||||||
|
|
||||||
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
||||||
if (!version)
|
if (!version)
|
||||||
@@ -176,7 +185,8 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_command = tmp.toString();
|
m_command = tmp.toString();
|
||||||
m_workingDirectory = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();
|
m_workingDirectory = bc ? bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString()
|
||||||
|
: QString();
|
||||||
|
|
||||||
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--verbose"));
|
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--verbose"));
|
||||||
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--output"));
|
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--output"));
|
||||||
@@ -213,8 +223,6 @@ bool AndroidDeployQtStep::init(QList<const BuildStep *> &earlierSteps)
|
|||||||
}
|
}
|
||||||
m_environment = bc ? bc->environment() : Utils::Environment();
|
m_environment = bc ? bc->environment() : Utils::Environment();
|
||||||
|
|
||||||
m_buildDirectory = bc ? bc->buildDirectory().toString() : QString();
|
|
||||||
|
|
||||||
m_adbPath = AndroidConfigurations::currentConfig().adbToolPath().toString();
|
m_adbPath = AndroidConfigurations::currentConfig().adbToolPath().toString();
|
||||||
|
|
||||||
AndroidAvdManager avdManager;
|
AndroidAvdManager avdManager;
|
||||||
@@ -394,31 +402,18 @@ void AndroidDeployQtStep::run(QFutureInterface<bool> &fi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
emit addOutput(tr("Pulling files necessary for debugging."), OutputFormat::NormalMessage);
|
emit addOutput(tr("Pulling files necessary for debugging."), OutputFormat::NormalMessage);
|
||||||
|
for (auto itr = m_filesToPull.constBegin(); itr != m_filesToPull.constEnd(); ++itr) {
|
||||||
QString localAppProcessFile = QString::fromLatin1("%1/app_process").arg(m_buildDirectory);
|
QFile::remove(itr.value());
|
||||||
QFile::remove(localAppProcessFile);
|
|
||||||
|
|
||||||
foreach (const QString &remoteAppProcessFile, m_appProcessBinaries) {
|
|
||||||
runCommand(m_adbPath,
|
runCommand(m_adbPath,
|
||||||
AndroidDeviceInfo::adbSelector(m_serialNumber)
|
AndroidDeviceInfo::adbSelector(m_serialNumber)
|
||||||
<< QLatin1String("pull") << remoteAppProcessFile
|
<< "pull" << itr.key() << itr.value());
|
||||||
<< localAppProcessFile);
|
if (!QFileInfo::exists(itr.value())) {
|
||||||
if (QFileInfo::exists(localAppProcessFile))
|
emit addOutput(tr("Package deploy: Failed to pull \"%1\" to \"%2\".")
|
||||||
break;
|
.arg(itr.key())
|
||||||
|
.arg(itr.value()), OutputFormat::ErrorMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QFileInfo::exists(localAppProcessFile)) {
|
|
||||||
returnValue = Failure;
|
|
||||||
emit addOutput(tr("Package deploy: Failed to pull \"%1\" to \"%2\".")
|
|
||||||
.arg(m_appProcessBinaries.join(QLatin1String("\", \"")))
|
|
||||||
.arg(localAppProcessFile), OutputFormat::ErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
runCommand(m_adbPath,
|
|
||||||
AndroidDeviceInfo::adbSelector(m_serialNumber) << QLatin1String("pull")
|
|
||||||
<< QLatin1String("/system/") + m_libdir + QLatin1String("/libc.so")
|
|
||||||
<< QString::fromLatin1("%1/libc.so").arg(m_buildDirectory));
|
|
||||||
|
|
||||||
reportRunResult(fi, returnValue == NoError);
|
reportRunResult(fi, returnValue == NoError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -113,11 +113,10 @@ private:
|
|||||||
|
|
||||||
Utils::FileName m_manifestName;
|
Utils::FileName m_manifestName;
|
||||||
QString m_serialNumber;
|
QString m_serialNumber;
|
||||||
QString m_buildDirectory;
|
|
||||||
QString m_avdName;
|
QString m_avdName;
|
||||||
QString m_apkPath;
|
QString m_apkPath;
|
||||||
|
QMap<QString, QString> m_filesToPull;
|
||||||
QStringList m_appProcessBinaries;
|
QStringList m_appProcessBinaries;
|
||||||
QString m_libdir;
|
|
||||||
|
|
||||||
QString m_targetArch;
|
QString m_targetArch;
|
||||||
bool m_uninstallPreviousPackage = false;
|
bool m_uninstallPreviousPackage = false;
|
||||||
|
@@ -548,18 +548,21 @@ QRect BinEditorWidget::cursorRect() const
|
|||||||
return QRect(x, y, w, m_lineHeight);
|
return QRect(x, y, w, m_lineHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
int BinEditorWidget::posAt(const QPoint &pos) const
|
Utils::optional<qint64> BinEditorWidget::posAt(const QPoint &pos, bool includeEmptyArea) const
|
||||||
{
|
{
|
||||||
const int xoffset = horizontalScrollBar()->value();
|
const int xoffset = horizontalScrollBar()->value();
|
||||||
int x = xoffset + pos.x() - m_margin - m_labelWidth;
|
int x = xoffset + pos.x() - m_margin - m_labelWidth;
|
||||||
|
if (!includeEmptyArea && x < 0)
|
||||||
|
return Utils::nullopt;
|
||||||
int column = qMin(15, qMax(0,x) / m_columnWidth);
|
int column = qMin(15, qMax(0,x) / m_columnWidth);
|
||||||
const qint64 topLine = verticalScrollBar()->value();
|
const qint64 topLine = verticalScrollBar()->value();
|
||||||
const qint64 line = topLine + pos.y() / m_lineHeight;
|
const qint64 line = topLine + pos.y() / m_lineHeight;
|
||||||
|
|
||||||
|
// "clear text" area
|
||||||
if (x > m_bytesPerLine * m_columnWidth + m_charWidth/2) {
|
if (x > m_bytesPerLine * m_columnWidth + m_charWidth/2) {
|
||||||
x -= m_bytesPerLine * m_columnWidth + m_charWidth;
|
x -= m_bytesPerLine * m_columnWidth + m_charWidth;
|
||||||
for (column = 0; column < 15; ++column) {
|
for (column = 0; column < 16; ++column) {
|
||||||
const int dataPos = line * m_bytesPerLine + column;
|
const qint64 dataPos = line * m_bytesPerLine + column;
|
||||||
if (dataPos < 0 || dataPos >= m_size)
|
if (dataPos < 0 || dataPos >= m_size)
|
||||||
break;
|
break;
|
||||||
QChar qc(QLatin1Char(dataAt(dataPos)));
|
QChar qc(QLatin1Char(dataAt(dataPos)));
|
||||||
@@ -569,9 +572,14 @@ int BinEditorWidget::posAt(const QPoint &pos) const
|
|||||||
if (x <= 0)
|
if (x <= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!includeEmptyArea && x > 0) // right of the text area
|
||||||
|
return Utils::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return qMin(m_size - 1, line * m_bytesPerLine + column);
|
const qint64 bytePos = line * m_bytesPerLine + column;
|
||||||
|
if (!includeEmptyArea && bytePos >= m_size)
|
||||||
|
return Utils::nullopt;
|
||||||
|
return qMin(m_size - 1, bytePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BinEditorWidget::inTextArea(const QPoint &pos) const
|
bool BinEditorWidget::inTextArea(const QPoint &pos) const
|
||||||
@@ -1041,7 +1049,7 @@ void BinEditorWidget::mousePressEvent(QMouseEvent *e)
|
|||||||
if (e->button() != Qt::LeftButton)
|
if (e->button() != Qt::LeftButton)
|
||||||
return;
|
return;
|
||||||
MoveMode moveMode = e->modifiers() & Qt::ShiftModifier ? KeepAnchor : MoveAnchor;
|
MoveMode moveMode = e->modifiers() & Qt::ShiftModifier ? KeepAnchor : MoveAnchor;
|
||||||
setCursorPosition(posAt(e->pos()), moveMode);
|
setCursorPosition(posAt(e->pos()).value(), moveMode);
|
||||||
setBlinkingCursorEnabled(true);
|
setBlinkingCursorEnabled(true);
|
||||||
if (m_hexCursor == inTextArea(e->pos())) {
|
if (m_hexCursor == inTextArea(e->pos())) {
|
||||||
m_hexCursor = !m_hexCursor;
|
m_hexCursor = !m_hexCursor;
|
||||||
@@ -1053,7 +1061,7 @@ void BinEditorWidget::mouseMoveEvent(QMouseEvent *e)
|
|||||||
{
|
{
|
||||||
if (!(e->buttons() & Qt::LeftButton))
|
if (!(e->buttons() & Qt::LeftButton))
|
||||||
return;
|
return;
|
||||||
setCursorPosition(posAt(e->pos()), KeepAnchor);
|
setCursorPosition(posAt(e->pos()).value(), KeepAnchor);
|
||||||
if (m_hexCursor == inTextArea(e->pos())) {
|
if (m_hexCursor == inTextArea(e->pos())) {
|
||||||
m_hexCursor = !m_hexCursor;
|
m_hexCursor = !m_hexCursor;
|
||||||
updateLines();
|
updateLines();
|
||||||
@@ -1144,17 +1152,17 @@ bool BinEditorWidget::event(QEvent *e)
|
|||||||
|
|
||||||
QString BinEditorWidget::toolTip(const QHelpEvent *helpEvent) const
|
QString BinEditorWidget::toolTip(const QHelpEvent *helpEvent) const
|
||||||
{
|
{
|
||||||
int selStart = selectionStart();
|
qint64 selStart = selectionStart();
|
||||||
int selEnd = selectionEnd();
|
qint64 selEnd = selectionEnd();
|
||||||
int byteCount = std::min(8, selEnd - selStart + 1);
|
qint64 byteCount = std::min(8LL, selEnd - selStart + 1);
|
||||||
|
|
||||||
// check even position against selection line by line
|
// check even position against selection line by line
|
||||||
bool insideSelection = false;
|
bool insideSelection = false;
|
||||||
int startInLine = selStart;
|
qint64 startInLine = selStart;
|
||||||
do {
|
do {
|
||||||
const int lineIndex = startInLine / m_bytesPerLine;
|
const qint64 lineIndex = startInLine / m_bytesPerLine;
|
||||||
const int endOfLine = (lineIndex + 1) * m_bytesPerLine - 1;
|
const qint64 endOfLine = (lineIndex + 1) * m_bytesPerLine - 1;
|
||||||
const int endInLine = std::min(selEnd, endOfLine);
|
const qint64 endInLine = std::min(selEnd, endOfLine);
|
||||||
const QPoint &startPoint = offsetToPos(startInLine);
|
const QPoint &startPoint = offsetToPos(startInLine);
|
||||||
const QPoint &endPoint = offsetToPos(endInLine) + QPoint(m_columnWidth, 0);
|
const QPoint &endPoint = offsetToPos(endInLine) + QPoint(m_columnWidth, 0);
|
||||||
QRect selectionLineRect(startPoint, endPoint);
|
QRect selectionLineRect(startPoint, endPoint);
|
||||||
@@ -1167,7 +1175,10 @@ QString BinEditorWidget::toolTip(const QHelpEvent *helpEvent) const
|
|||||||
} while (startInLine <= selEnd);
|
} while (startInLine <= selEnd);
|
||||||
if (!insideSelection) {
|
if (!insideSelection) {
|
||||||
// show popup for byte under cursor
|
// show popup for byte under cursor
|
||||||
selStart = posAt(helpEvent->pos());
|
Utils::optional<qint64> pos = posAt(helpEvent->pos(), /*includeEmptyArea*/false);
|
||||||
|
if (!pos)
|
||||||
|
return QString();
|
||||||
|
selStart = pos.value();
|
||||||
selEnd = selStart;
|
selEnd = selStart;
|
||||||
byteCount = 1;
|
byteCount = 1;
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
#include "markup.h"
|
#include "markup.h"
|
||||||
#include "bineditorservice.h"
|
#include "bineditorservice.h"
|
||||||
|
|
||||||
|
#include <utils/optional.h>
|
||||||
|
|
||||||
#include <QBasicTimer>
|
#include <QBasicTimer>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
@@ -210,7 +212,7 @@ private:
|
|||||||
QBasicTimer m_cursorBlinkTimer;
|
QBasicTimer m_cursorBlinkTimer;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
int posAt(const QPoint &pos) const;
|
Utils::optional<qint64> posAt(const QPoint &pos, bool includeEmptyArea = true) const;
|
||||||
bool inTextArea(const QPoint &pos) const;
|
bool inTextArea(const QPoint &pos) const;
|
||||||
QRect cursorRect() const;
|
QRect cursorRect() const;
|
||||||
void updateLines();
|
void updateLines();
|
||||||
|
@@ -123,6 +123,7 @@ bool CMakeRunConfiguration::fromMap(const QVariantMap &map)
|
|||||||
m_executable = extraId;
|
m_executable = extraId;
|
||||||
if (m_title.isEmpty())
|
if (m_title.isEmpty())
|
||||||
m_title = extraId;
|
m_title = extraId;
|
||||||
|
setDefaultDisplayName(m_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
78
src/plugins/diffeditor/descriptionwidgetwatcher.cpp
Normal file
78
src/plugins/diffeditor/descriptionwidgetwatcher.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "descriptionwidgetwatcher.h"
|
||||||
|
#include "diffeditor.h"
|
||||||
|
#include "diffeditorcontroller.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/documentmodel.h>
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
|
||||||
|
namespace DiffEditor {
|
||||||
|
|
||||||
|
DescriptionWidgetWatcher::DescriptionWidgetWatcher(DiffEditorController *controller)
|
||||||
|
: QObject(controller), m_document(controller->document())
|
||||||
|
{
|
||||||
|
const QList<IEditor *> editors = DocumentModel::editorsForDocument(controller->document());
|
||||||
|
for (auto *editor : editors) {
|
||||||
|
if (TextEditor::TextEditorWidget *widget = descriptionWidget(editor))
|
||||||
|
m_widgets.append(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(EditorManager::instance(), &EditorManager::editorOpened,
|
||||||
|
[this](IEditor *editor) {
|
||||||
|
if (TextEditor::TextEditorWidget *widget = descriptionWidget(editor)) {
|
||||||
|
m_widgets.append(widget);
|
||||||
|
emit descriptionWidgetAdded(widget);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(EditorManager::instance(), &EditorManager::editorAboutToClose,
|
||||||
|
[this](IEditor *editor) {
|
||||||
|
if (TextEditor::TextEditorWidget *widget = descriptionWidget(editor)) {
|
||||||
|
emit descriptionWidgetRemoved(widget);
|
||||||
|
m_widgets.removeAll(widget);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<TextEditor::TextEditorWidget *> DescriptionWidgetWatcher::descriptionWidgets() const
|
||||||
|
{
|
||||||
|
return m_widgets;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditor::TextEditorWidget *DescriptionWidgetWatcher::descriptionWidget(Core::IEditor *editor) const
|
||||||
|
{
|
||||||
|
if (Internal::DiffEditor *diffEditor = qobject_cast<Internal::DiffEditor *>(editor)) {
|
||||||
|
if (diffEditor->document() == m_document)
|
||||||
|
return diffEditor->descriptionWidget();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace DiffEditor
|
60
src/plugins/diffeditor/descriptionwidgetwatcher.h
Normal file
60
src/plugins/diffeditor/descriptionwidgetwatcher.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "diffeditor_global.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class IDocument;
|
||||||
|
class IEditor;
|
||||||
|
}
|
||||||
|
namespace TextEditor { class TextEditorWidget; }
|
||||||
|
|
||||||
|
namespace DiffEditor {
|
||||||
|
|
||||||
|
class DiffEditorController;
|
||||||
|
|
||||||
|
class DIFFEDITOR_EXPORT DescriptionWidgetWatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DescriptionWidgetWatcher(DiffEditorController *controller);
|
||||||
|
QList<TextEditor::TextEditorWidget *> descriptionWidgets() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void descriptionWidgetAdded(TextEditor::TextEditorWidget *editor);
|
||||||
|
void descriptionWidgetRemoved(TextEditor::TextEditorWidget *editor);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextEditor::TextEditorWidget *descriptionWidget(Core::IEditor *editor) const;
|
||||||
|
|
||||||
|
QList<TextEditor::TextEditorWidget *> m_widgets;
|
||||||
|
Core::IDocument *m_document = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace DiffEditor
|
@@ -81,22 +81,11 @@ public:
|
|||||||
|
|
||||||
virtual QSize sizeHint() const override;
|
virtual QSize sizeHint() const override;
|
||||||
|
|
||||||
signals:
|
|
||||||
void requestBranchList();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
|
||||||
|
|
||||||
void setDisplaySettings(const DisplaySettings &ds) override;
|
void setDisplaySettings(const DisplaySettings &ds) override;
|
||||||
void setMarginSettings(const MarginSettings &ms) override;
|
void setMarginSettings(const MarginSettings &ms) override;
|
||||||
|
|
||||||
bool findContentsUnderCursor(const QTextCursor &cursor);
|
|
||||||
void highlightCurrentContents();
|
|
||||||
void handleCurrentContents();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTextCursor m_currentCursor;
|
|
||||||
Core::IContext *m_context;
|
Core::IContext *m_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,68 +142,6 @@ void DescriptionEditorWidget::setMarginSettings(const MarginSettings &ms)
|
|||||||
TextEditorWidget::setMarginSettings(MarginSettings());
|
TextEditorWidget::setMarginSettings(MarginSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionEditorWidget::mouseMoveEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
if (e->buttons()) {
|
|
||||||
TextEditorWidget::mouseMoveEvent(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::CursorShape cursorShape;
|
|
||||||
|
|
||||||
const QTextCursor cursor = cursorForPosition(e->pos());
|
|
||||||
if (findContentsUnderCursor(cursor)) {
|
|
||||||
highlightCurrentContents();
|
|
||||||
cursorShape = Qt::PointingHandCursor;
|
|
||||||
} else {
|
|
||||||
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
|
|
||||||
cursorShape = Qt::IBeamCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditorWidget::mouseMoveEvent(e);
|
|
||||||
viewport()->setCursor(cursorShape);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionEditorWidget::mouseReleaseEvent(QMouseEvent *e)
|
|
||||||
{
|
|
||||||
if (e->button() == Qt::LeftButton && !(e->modifiers() & Qt::ShiftModifier)) {
|
|
||||||
const QTextCursor cursor = cursorForPosition(e->pos());
|
|
||||||
if (findContentsUnderCursor(cursor)) {
|
|
||||||
handleCurrentContents();
|
|
||||||
e->accept();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextEditorWidget::mouseReleaseEvent(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DescriptionEditorWidget::findContentsUnderCursor(const QTextCursor &cursor)
|
|
||||||
{
|
|
||||||
m_currentCursor = cursor;
|
|
||||||
return cursor.block().text() == Constants::EXPAND_BRANCHES;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionEditorWidget::highlightCurrentContents()
|
|
||||||
{
|
|
||||||
QTextEdit::ExtraSelection sel;
|
|
||||||
sel.cursor = m_currentCursor;
|
|
||||||
sel.cursor.select(QTextCursor::LineUnderCursor);
|
|
||||||
sel.format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
|
||||||
const QColor textColor = TextEditorSettings::fontSettings().formatFor(C_TEXT).foreground();
|
|
||||||
sel.format.setUnderlineColor(textColor.isValid() ? textColor : palette().color(QPalette::Foreground));
|
|
||||||
setExtraSelections(TextEditorWidget::OtherSelection,
|
|
||||||
QList<QTextEdit::ExtraSelection>() << sel);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionEditorWidget::handleCurrentContents()
|
|
||||||
{
|
|
||||||
m_currentCursor.select(QTextCursor::LineUnderCursor);
|
|
||||||
m_currentCursor.removeSelectedText();
|
|
||||||
m_currentCursor.insertText("Branches: Expanding...");
|
|
||||||
emit requestBranchList();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////// DiffEditor //////////////////////////////////
|
///////////////////////////////// DiffEditor //////////////////////////////////
|
||||||
|
|
||||||
DiffEditor::DiffEditor()
|
DiffEditor::DiffEditor()
|
||||||
@@ -296,8 +223,6 @@ void DiffEditor::setDocument(QSharedPointer<DiffEditorDocument> doc)
|
|||||||
|
|
||||||
m_document = doc;
|
m_document = doc;
|
||||||
|
|
||||||
connect(m_descriptionWidget, &DescriptionEditorWidget::requestBranchList,
|
|
||||||
m_document.data(), &DiffEditorDocument::requestMoreInformation);
|
|
||||||
connect(m_document.data(), &DiffEditorDocument::documentChanged,
|
connect(m_document.data(), &DiffEditorDocument::documentChanged,
|
||||||
this, &DiffEditor::documentHasChanged);
|
this, &DiffEditor::documentHasChanged);
|
||||||
connect(m_document.data(), &DiffEditorDocument::descriptionChanged,
|
connect(m_document.data(), &DiffEditorDocument::descriptionChanged,
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
DEFINES += DIFFEDITOR_LIBRARY
|
DEFINES += DIFFEDITOR_LIBRARY
|
||||||
include(../../qtcreatorplugin.pri)
|
include(../../qtcreatorplugin.pri)
|
||||||
|
|
||||||
HEADERS += diffeditor_global.h \
|
HEADERS += \
|
||||||
|
descriptionwidgetwatcher.h \
|
||||||
|
diffeditor_global.h \
|
||||||
diffeditor.h \
|
diffeditor.h \
|
||||||
diffeditorconstants.h \
|
diffeditorconstants.h \
|
||||||
diffeditorcontroller.h \
|
diffeditorcontroller.h \
|
||||||
@@ -17,7 +19,9 @@ HEADERS += diffeditor_global.h \
|
|||||||
unifieddiffeditorwidget.h \
|
unifieddiffeditorwidget.h \
|
||||||
diffeditoricons.h
|
diffeditoricons.h
|
||||||
|
|
||||||
SOURCES += diffeditor.cpp \
|
SOURCES += \
|
||||||
|
descriptionwidgetwatcher.cpp \
|
||||||
|
diffeditor.cpp \
|
||||||
diffeditorcontroller.cpp \
|
diffeditorcontroller.cpp \
|
||||||
diffeditordocument.cpp \
|
diffeditordocument.cpp \
|
||||||
diffeditorfactory.cpp \
|
diffeditorfactory.cpp \
|
||||||
|
@@ -14,6 +14,8 @@ QtcPlugin {
|
|||||||
]
|
]
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
|
"descriptionwidgetwatcher.cpp",
|
||||||
|
"descriptionwidgetwatcher.h",
|
||||||
"diffeditor.cpp",
|
"diffeditor.cpp",
|
||||||
"diffeditor.h",
|
"diffeditor.h",
|
||||||
"diffeditor.qrc",
|
"diffeditor.qrc",
|
||||||
|
@@ -41,7 +41,5 @@ const char UNIFIED_VIEW_ID[] = "DiffEditor.Unified";
|
|||||||
|
|
||||||
const char G_TOOLS_DIFF[] = "QtCreator.Group.Tools.Options";
|
const char G_TOOLS_DIFF[] = "QtCreator.Group.Tools.Options";
|
||||||
|
|
||||||
const char EXPAND_BRANCHES[] = "Branches: <Expand>";
|
|
||||||
|
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
} // namespace DiffEditor
|
} // namespace DiffEditor
|
||||||
|
@@ -65,12 +65,6 @@ bool DiffEditorController::ignoreWhitespace() const
|
|||||||
return m_document->ignoreWhitespace();
|
return m_document->ignoreWhitespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DiffEditorController::revisionFromDescription() const
|
|
||||||
{
|
|
||||||
// TODO: This is specific for git and does not belong here at all!
|
|
||||||
return m_document->description().mid(7, 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString DiffEditorController::makePatch(int fileIndex, int chunkIndex,
|
QString DiffEditorController::makePatch(int fileIndex, int chunkIndex,
|
||||||
PatchOptions options) const
|
PatchOptions options) const
|
||||||
{
|
{
|
||||||
@@ -105,18 +99,9 @@ void DiffEditorController::setDescription(const QString &description)
|
|||||||
m_document->setDescription(description);
|
m_document->setDescription(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffEditorController::branchesReceived(const QString &branches)
|
QString DiffEditorController::description() const
|
||||||
{
|
{
|
||||||
QString tmp = m_document->description();
|
return m_document->description();
|
||||||
tmp.replace(Constants::EXPAND_BRANCHES, branches);
|
|
||||||
m_document->setDescription(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiffEditorController::requestMoreInformation()
|
|
||||||
{
|
|
||||||
const QString rev = revisionFromDescription();
|
|
||||||
if (!rev.isEmpty())
|
|
||||||
emit requestInformationForCommit(rev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -51,8 +51,6 @@ public:
|
|||||||
int contextLineCount() const;
|
int contextLineCount() const;
|
||||||
bool ignoreWhitespace() const;
|
bool ignoreWhitespace() const;
|
||||||
|
|
||||||
QString revisionFromDescription() const;
|
|
||||||
|
|
||||||
enum PatchOption {
|
enum PatchOption {
|
||||||
NoOption = 0,
|
NoOption = 0,
|
||||||
Revert = 1,
|
Revert = 1,
|
||||||
@@ -65,13 +63,12 @@ public:
|
|||||||
const QString &displayName);
|
const QString &displayName);
|
||||||
static DiffEditorController *controller(Core::IDocument *document);
|
static DiffEditorController *controller(Core::IDocument *document);
|
||||||
|
|
||||||
void branchesReceived(const QString &branches);
|
|
||||||
void requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex);
|
void requestChunkActions(QMenu *menu, int fileIndex, int chunkIndex);
|
||||||
bool chunkExists(int fileIndex, int chunkIndex) const;
|
bool chunkExists(int fileIndex, int chunkIndex) const;
|
||||||
|
Core::IDocument *document() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex);
|
void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex);
|
||||||
void requestInformationForCommit(const QString &revision);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// reloadFinished() should be called
|
// reloadFinished() should be called
|
||||||
@@ -84,14 +81,11 @@ protected:
|
|||||||
const QString &baseDirectory = QString(),
|
const QString &baseDirectory = QString(),
|
||||||
const QString &startupFile = QString());
|
const QString &startupFile = QString());
|
||||||
void setDescription(const QString &description);
|
void setDescription(const QString &description);
|
||||||
|
QString description() const;
|
||||||
void forceContextLineCount(int lines);
|
void forceContextLineCount(int lines);
|
||||||
Core::IDocument *document() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void requestMoreInformation();
|
|
||||||
|
|
||||||
Internal::DiffEditorDocument *const m_document;
|
Internal::DiffEditorDocument *const m_document;
|
||||||
|
|
||||||
bool m_isReloading = false;
|
bool m_isReloading = false;
|
||||||
|
|
||||||
friend class Internal::DiffEditorDocument;
|
friend class Internal::DiffEditorDocument;
|
||||||
|
@@ -69,11 +69,6 @@ void DiffEditorDocument::setController(DiffEditorController *controller)
|
|||||||
if (m_controller)
|
if (m_controller)
|
||||||
m_controller->deleteLater();
|
m_controller->deleteLater();
|
||||||
m_controller = controller;
|
m_controller = controller;
|
||||||
|
|
||||||
if (m_controller) {
|
|
||||||
connect(this, &DiffEditorDocument::requestMoreInformation,
|
|
||||||
m_controller, &DiffEditorController::requestMoreInformation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DiffEditorController *DiffEditorDocument::controller() const
|
DiffEditorController *DiffEditorDocument::controller() const
|
||||||
|
@@ -90,7 +90,6 @@ signals:
|
|||||||
void temporaryStateChanged();
|
void temporaryStateChanged();
|
||||||
void documentChanged();
|
void documentChanged();
|
||||||
void descriptionChanged();
|
void descriptionChanged();
|
||||||
void requestMoreInformation();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void beginReload();
|
void beginReload();
|
||||||
|
@@ -62,9 +62,14 @@
|
|||||||
#include <vcsbase/vcscommand.h>
|
#include <vcsbase/vcscommand.h>
|
||||||
#include <vcsbase/vcsoutputwindow.h>
|
#include <vcsbase/vcsoutputwindow.h>
|
||||||
|
|
||||||
|
#include <diffeditor/descriptionwidgetwatcher.h>
|
||||||
#include <diffeditor/diffeditorconstants.h>
|
#include <diffeditor/diffeditorconstants.h>
|
||||||
#include <diffeditor/diffeditorcontroller.h>
|
#include <diffeditor/diffeditorcontroller.h>
|
||||||
#include <diffeditor/diffutils.h>
|
#include <diffeditor/diffutils.h>
|
||||||
|
|
||||||
|
#include <texteditor/fontsettings.h>
|
||||||
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@@ -76,8 +81,9 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QRegExp>
|
#include <QRegExp>
|
||||||
#include <QTextCodec>
|
#include <QTextBlock>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
#include <QTextCodec>
|
||||||
|
|
||||||
const char GIT_DIRECTORY[] = ".git";
|
const char GIT_DIRECTORY[] = ".git";
|
||||||
const char graphLogFormatC[] = "%h %d %an %s %ci";
|
const char graphLogFormatC[] = "%h %d %an %s %ci";
|
||||||
@@ -112,6 +118,153 @@ const unsigned silentFlags = unsigned(VcsCommand::SuppressCommandLogging
|
|||||||
| VcsCommand::SuppressStdErr
|
| VcsCommand::SuppressStdErr
|
||||||
| VcsCommand::SuppressFailMessage);
|
| VcsCommand::SuppressFailMessage);
|
||||||
|
|
||||||
|
static QString branchesDisplay(const QString &prefix, QStringList *branches, bool *first)
|
||||||
|
{
|
||||||
|
const int limit = 12;
|
||||||
|
const int count = branches->count();
|
||||||
|
int more = 0;
|
||||||
|
QString output;
|
||||||
|
if (*first)
|
||||||
|
*first = false;
|
||||||
|
else
|
||||||
|
output += QString(sizeof(BRANCHES_PREFIX) - 1, ' '); // Align
|
||||||
|
output += prefix + ": ";
|
||||||
|
// If there are more than 'limit' branches, list limit/2 (first limit/4 and last limit/4)
|
||||||
|
if (count > limit) {
|
||||||
|
const int leave = limit / 2;
|
||||||
|
more = count - leave;
|
||||||
|
branches->erase(branches->begin() + leave / 2 + 1, branches->begin() + count - leave / 2);
|
||||||
|
(*branches)[leave / 2] = "...";
|
||||||
|
}
|
||||||
|
output += branches->join(", ");
|
||||||
|
//: Displayed after the untranslated message "Branches: branch1, branch2 'and %n more'"
|
||||||
|
// in git show.
|
||||||
|
if (more > 0)
|
||||||
|
output += ' ' + GitClient::tr("and %n more", 0, more);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DescriptionWidgetDecorator : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DescriptionWidgetDecorator(DescriptionWidgetWatcher *watcher);
|
||||||
|
|
||||||
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void branchListRequested();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool checkContentsUnderCursor(const QTextCursor &cursor) const;
|
||||||
|
void highlightCurrentContents(TextEditor::TextEditorWidget *textEditor,
|
||||||
|
const QTextCursor &cursor);
|
||||||
|
void handleCurrentContents(const QTextCursor &cursor);
|
||||||
|
void addWatch(TextEditor::TextEditorWidget *widget);
|
||||||
|
void removeWatch(TextEditor::TextEditorWidget *widget);
|
||||||
|
|
||||||
|
DescriptionWidgetWatcher *m_watcher;
|
||||||
|
QHash<QObject *, TextEditor::TextEditorWidget *> m_viewportToTextEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
DescriptionWidgetDecorator::DescriptionWidgetDecorator(DescriptionWidgetWatcher *watcher)
|
||||||
|
: QObject(),
|
||||||
|
m_watcher(watcher)
|
||||||
|
{
|
||||||
|
QList<TextEditor::TextEditorWidget *> widgets = m_watcher->descriptionWidgets();
|
||||||
|
for (auto *widget : widgets)
|
||||||
|
addWatch(widget);
|
||||||
|
|
||||||
|
connect(m_watcher, &DescriptionWidgetWatcher::descriptionWidgetAdded,
|
||||||
|
this, &DescriptionWidgetDecorator::addWatch);
|
||||||
|
connect(m_watcher, &DescriptionWidgetWatcher::descriptionWidgetRemoved,
|
||||||
|
this, &DescriptionWidgetDecorator::removeWatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptionWidgetDecorator::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
TextEditor::TextEditorWidget *textEditor = m_viewportToTextEditor.value(watched);
|
||||||
|
if (!textEditor)
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
|
||||||
|
if (event->type() == QEvent::MouseMove) {
|
||||||
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
|
if (mouseEvent->buttons())
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
|
||||||
|
Qt::CursorShape cursorShape;
|
||||||
|
|
||||||
|
const QTextCursor cursor = textEditor->cursorForPosition(mouseEvent->pos());
|
||||||
|
if (checkContentsUnderCursor(cursor)) {
|
||||||
|
highlightCurrentContents(textEditor, cursor);
|
||||||
|
cursorShape = Qt::PointingHandCursor;
|
||||||
|
} else {
|
||||||
|
textEditor->setExtraSelections(TextEditor::TextEditorWidget::OtherSelection,
|
||||||
|
QList<QTextEdit::ExtraSelection>());
|
||||||
|
cursorShape = Qt::IBeamCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = QObject::eventFilter(watched, event);
|
||||||
|
textEditor->viewport()->setCursor(cursorShape);
|
||||||
|
return ret;
|
||||||
|
} else if (event->type() == QEvent::MouseButtonRelease) {
|
||||||
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
|
|
||||||
|
if (mouseEvent->button() == Qt::LeftButton && !(mouseEvent->modifiers() & Qt::ShiftModifier)) {
|
||||||
|
const QTextCursor cursor = textEditor->cursorForPosition(mouseEvent->pos());
|
||||||
|
if (checkContentsUnderCursor(cursor)) {
|
||||||
|
handleCurrentContents(cursor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptionWidgetDecorator::checkContentsUnderCursor(const QTextCursor &cursor) const
|
||||||
|
{
|
||||||
|
return cursor.block().text() == Constants::EXPAND_BRANCHES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionWidgetDecorator::highlightCurrentContents(
|
||||||
|
TextEditor::TextEditorWidget *textEditor, const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
QTextEdit::ExtraSelection sel;
|
||||||
|
sel.cursor = cursor;
|
||||||
|
sel.cursor.select(QTextCursor::LineUnderCursor);
|
||||||
|
sel.format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
|
||||||
|
const QColor textColor = TextEditor::TextEditorSettings::fontSettings().formatFor(TextEditor::C_TEXT).foreground();
|
||||||
|
sel.format.setUnderlineColor(textColor.isValid() ? textColor : textEditor->palette().color(QPalette::Foreground));
|
||||||
|
textEditor->setExtraSelections(TextEditor::TextEditorWidget::OtherSelection,
|
||||||
|
QList<QTextEdit::ExtraSelection>() << sel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionWidgetDecorator::handleCurrentContents(const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
QTextCursor copy = cursor;
|
||||||
|
|
||||||
|
copy.select(QTextCursor::LineUnderCursor);
|
||||||
|
copy.removeSelectedText();
|
||||||
|
copy.insertText("Branches: Expanding...");
|
||||||
|
emit branchListRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionWidgetDecorator::addWatch(TextEditor::TextEditorWidget *widget)
|
||||||
|
{
|
||||||
|
m_viewportToTextEditor.insert(widget->viewport(), widget);
|
||||||
|
widget->viewport()->installEventFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionWidgetDecorator::removeWatch(TextEditor::TextEditorWidget *widget)
|
||||||
|
{
|
||||||
|
widget->viewport()->removeEventFilter(this);
|
||||||
|
m_viewportToTextEditor.remove(widget->viewport());
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
class GitDiffEditorController : public VcsBaseDiffEditorController
|
class GitDiffEditorController : public VcsBaseDiffEditorController
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -124,13 +277,75 @@ protected:
|
|||||||
|
|
||||||
QStringList addConfigurationArguments(const QStringList &args) const;
|
QStringList addConfigurationArguments(const QStringList &args) const;
|
||||||
QStringList addHeadWhenCommandInProgress() const;
|
QStringList addHeadWhenCommandInProgress() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateBranchList();
|
||||||
|
|
||||||
|
DescriptionWidgetWatcher m_watcher;
|
||||||
|
DescriptionWidgetDecorator m_decorator;
|
||||||
};
|
};
|
||||||
|
|
||||||
GitDiffEditorController::GitDiffEditorController(IDocument *document, const QString &workingDirectory) :
|
GitDiffEditorController::GitDiffEditorController(IDocument *document, const QString &workingDirectory) :
|
||||||
VcsBaseDiffEditorController(document, GitPlugin::client(), workingDirectory)
|
VcsBaseDiffEditorController(document, GitPlugin::client(), workingDirectory),
|
||||||
|
m_watcher(this),
|
||||||
|
m_decorator(&m_watcher)
|
||||||
{
|
{
|
||||||
|
connect(&m_decorator, &DescriptionWidgetDecorator::branchListRequested,
|
||||||
|
this, &GitDiffEditorController::updateBranchList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GitDiffEditorController::updateBranchList()
|
||||||
|
{
|
||||||
|
const QString revision = description().mid(7, 12);
|
||||||
|
if (revision.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QString workingDirectory = baseDirectory();
|
||||||
|
VcsCommand *command = GitPlugin::client()->vcsExec(
|
||||||
|
workingDirectory, {"branch", noColorOption, "-a", "--contains", revision}, nullptr,
|
||||||
|
false, 0, workingDirectory);
|
||||||
|
connect(command, &VcsCommand::stdOutText, [this](const QString &text) {
|
||||||
|
const QString remotePrefix = "remotes/";
|
||||||
|
const QString localPrefix = "<Local>";
|
||||||
|
const int prefixLength = remotePrefix.length();
|
||||||
|
QString output = BRANCHES_PREFIX;
|
||||||
|
QStringList branches;
|
||||||
|
QString previousRemote = localPrefix;
|
||||||
|
bool first = true;
|
||||||
|
for (const QString &branch : text.split('\n')) {
|
||||||
|
const QString b = branch.mid(2).trimmed();
|
||||||
|
if (b.isEmpty())
|
||||||
|
continue;
|
||||||
|
if (b.startsWith(remotePrefix)) {
|
||||||
|
const int nextSlash = b.indexOf('/', prefixLength);
|
||||||
|
if (nextSlash < 0)
|
||||||
|
continue;
|
||||||
|
const QString remote = b.mid(prefixLength, nextSlash - prefixLength);
|
||||||
|
if (remote != previousRemote) {
|
||||||
|
output += branchesDisplay(previousRemote, &branches, &first) + '\n';
|
||||||
|
branches.clear();
|
||||||
|
previousRemote = remote;
|
||||||
|
}
|
||||||
|
branches << b.mid(nextSlash + 1);
|
||||||
|
} else {
|
||||||
|
branches << b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (branches.isEmpty()) {
|
||||||
|
if (previousRemote == localPrefix)
|
||||||
|
output += tr("<None>");
|
||||||
|
} else {
|
||||||
|
output += branchesDisplay(previousRemote, &branches, &first);
|
||||||
|
}
|
||||||
|
const QString branchList = output.trimmed();
|
||||||
|
QString newDescription = description();
|
||||||
|
newDescription.replace(Constants::EXPAND_BRANCHES, branchList);
|
||||||
|
setDescription(newDescription);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
|
||||||
void GitDiffEditorController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
|
void GitDiffEditorController::runCommand(const QList<QStringList> &args, QTextCodec *codec)
|
||||||
{
|
{
|
||||||
VcsBaseDiffEditorController::runCommand(args, diffExecutionFlags(), codec);
|
VcsBaseDiffEditorController::runCommand(args, diffExecutionFlags(), codec);
|
||||||
@@ -679,8 +894,6 @@ void GitClient::requestReload(const QString &documentId, const QString &source,
|
|||||||
|
|
||||||
connect(controller, &DiffEditorController::chunkActionsRequested,
|
connect(controller, &DiffEditorController::chunkActionsRequested,
|
||||||
this, &GitClient::chunkActionsRequested, Qt::DirectConnection);
|
this, &GitClient::chunkActionsRequested, Qt::DirectConnection);
|
||||||
connect(controller, &DiffEditorController::requestInformationForCommit,
|
|
||||||
this, &GitClient::branchesForCommit);
|
|
||||||
|
|
||||||
VcsBasePlugin::setSource(document, sourceCopy);
|
VcsBasePlugin::setSource(document, sourceCopy);
|
||||||
EditorManager::activateEditorForDocument(document);
|
EditorManager::activateEditorForDocument(document);
|
||||||
@@ -1379,76 +1592,6 @@ void GitClient::synchronousTagsForCommit(const QString &workingDirectory, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString branchesDisplay(const QString &prefix, QStringList *branches, bool *first)
|
|
||||||
{
|
|
||||||
const int limit = 12;
|
|
||||||
const int count = branches->count();
|
|
||||||
int more = 0;
|
|
||||||
QString output;
|
|
||||||
if (*first)
|
|
||||||
*first = false;
|
|
||||||
else
|
|
||||||
output += QString(sizeof(BRANCHES_PREFIX) - 1, ' '); // Align
|
|
||||||
output += prefix + ": ";
|
|
||||||
// If there are more than 'limit' branches, list limit/2 (first limit/4 and last limit/4)
|
|
||||||
if (count > limit) {
|
|
||||||
const int leave = limit / 2;
|
|
||||||
more = count - leave;
|
|
||||||
branches->erase(branches->begin() + leave / 2 + 1, branches->begin() + count - leave / 2);
|
|
||||||
(*branches)[leave / 2] = "...";
|
|
||||||
}
|
|
||||||
output += branches->join(", ");
|
|
||||||
//: Displayed after the untranslated message "Branches: branch1, branch2 'and %n more'"
|
|
||||||
// in git show.
|
|
||||||
if (more > 0)
|
|
||||||
output += ' ' + GitClient::tr("and %n more", 0, more);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GitClient::branchesForCommit(const QString &revision)
|
|
||||||
{
|
|
||||||
auto controller = qobject_cast<DiffEditorController *>(sender());
|
|
||||||
QString workingDirectory = controller->baseDirectory();
|
|
||||||
VcsCommand *command = vcsExec(
|
|
||||||
workingDirectory, {"branch", noColorOption, "-a", "--contains", revision}, nullptr,
|
|
||||||
false, 0, workingDirectory);
|
|
||||||
connect(command, &VcsCommand::stdOutText, controller, [controller](const QString &text) {
|
|
||||||
const QString remotePrefix = "remotes/";
|
|
||||||
const QString localPrefix = "<Local>";
|
|
||||||
const int prefixLength = remotePrefix.length();
|
|
||||||
QString output = BRANCHES_PREFIX;
|
|
||||||
QStringList branches;
|
|
||||||
QString previousRemote = localPrefix;
|
|
||||||
bool first = true;
|
|
||||||
for (const QString &branch : text.split('\n')) {
|
|
||||||
const QString b = branch.mid(2).trimmed();
|
|
||||||
if (b.isEmpty())
|
|
||||||
continue;
|
|
||||||
if (b.startsWith(remotePrefix)) {
|
|
||||||
const int nextSlash = b.indexOf('/', prefixLength);
|
|
||||||
if (nextSlash < 0)
|
|
||||||
continue;
|
|
||||||
const QString remote = b.mid(prefixLength, nextSlash - prefixLength);
|
|
||||||
if (remote != previousRemote) {
|
|
||||||
output += branchesDisplay(previousRemote, &branches, &first) + '\n';
|
|
||||||
branches.clear();
|
|
||||||
previousRemote = remote;
|
|
||||||
}
|
|
||||||
branches << b.mid(nextSlash + 1);
|
|
||||||
} else {
|
|
||||||
branches << b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (branches.isEmpty()) {
|
|
||||||
if (previousRemote == localPrefix)
|
|
||||||
output += tr("<None>");
|
|
||||||
} else {
|
|
||||||
output += branchesDisplay(previousRemote, &branches, &first);
|
|
||||||
}
|
|
||||||
controller->branchesReceived(output.trimmed());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GitClient::isRemoteCommit(const QString &workingDirectory, const QString &commit)
|
bool GitClient::isRemoteCommit(const QString &workingDirectory, const QString &commit)
|
||||||
{
|
{
|
||||||
return !vcsFullySynchronousExec(
|
return !vcsFullySynchronousExec(
|
||||||
@@ -2110,7 +2253,7 @@ QString GitClient::extendedShowDescription(const QString &workingDirectory, cons
|
|||||||
// Empty line before headers and commit message
|
// Empty line before headers and commit message
|
||||||
const int emptyLine = modText.indexOf("\n\n");
|
const int emptyLine = modText.indexOf("\n\n");
|
||||||
if (emptyLine != -1)
|
if (emptyLine != -1)
|
||||||
modText.insert(emptyLine, QString('\n') + DiffEditor::Constants::EXPAND_BRANCHES);
|
modText.insert(emptyLine, QString('\n') + Constants::EXPAND_BRANCHES);
|
||||||
|
|
||||||
return modText;
|
return modText;
|
||||||
}
|
}
|
||||||
|
@@ -330,7 +330,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
void finishSubmoduleUpdate();
|
void finishSubmoduleUpdate();
|
||||||
void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex);
|
void chunkActionsRequested(QMenu *menu, int fileIndex, int chunkIndex);
|
||||||
void branchesForCommit(const QString &revision);
|
|
||||||
|
|
||||||
void stage(DiffEditor::DiffEditorController *diffController,
|
void stage(DiffEditor::DiffEditorController *diffController,
|
||||||
const QString &patch, bool revert);
|
const QString &patch, bool revert);
|
||||||
|
@@ -53,5 +53,7 @@ const char C_GITEDITORID[] = "Git Editor";
|
|||||||
|
|
||||||
const int OBSOLETE_COMMIT_AGE_IN_DAYS = 90;
|
const int OBSOLETE_COMMIT_AGE_IN_DAYS = 90;
|
||||||
|
|
||||||
|
const char EXPAND_BRANCHES[] = "Branches: <Expand>";
|
||||||
|
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
} // namespace Git
|
} // namespace Git
|
||||||
|
@@ -160,10 +160,13 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node, const Fi
|
|||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
// Prefer the cumulative file if it's non-empty, based on the assumption
|
// Prefer the cumulative file if it's non-empty, based on the assumption
|
||||||
// that it contains more "stuff".
|
// that it contains more "stuff".
|
||||||
vfs->readFile(file.toString(), QMakeVfs::VfsCumulative, &contents, &errorMessage);
|
int cid = vfs->idForFileName(file.toString(), QMakeVfs::VfsCumulative);
|
||||||
|
vfs->readFile(cid, &contents, &errorMessage);
|
||||||
// If the cumulative evaluation botched the file too much, try the exact one.
|
// If the cumulative evaluation botched the file too much, try the exact one.
|
||||||
if (contents.isEmpty())
|
if (contents.isEmpty()) {
|
||||||
vfs->readFile(file.toString(), QMakeVfs::VfsExact, &contents, &errorMessage);
|
int eid = vfs->idForFileName(file.toString(), QMakeVfs::VfsExact);
|
||||||
|
vfs->readFile(eid, &contents, &errorMessage);
|
||||||
|
}
|
||||||
auto resourceNode = new ResourceEditor::ResourceTopLevelNode(file, false, contents, vfolder);
|
auto resourceNode = new ResourceEditor::ResourceTopLevelNode(file, false, contents, vfolder);
|
||||||
vfolder->addNode(resourceNode);
|
vfolder->addNode(resourceNode);
|
||||||
}
|
}
|
||||||
|
@@ -237,7 +237,8 @@ QmakePriFile::~QmakePriFile()
|
|||||||
|
|
||||||
void QmakePriFile::scheduleUpdate()
|
void QmakePriFile::scheduleUpdate()
|
||||||
{
|
{
|
||||||
QtSupport::ProFileCacheManager::instance()->discardFile(filePath().toString());
|
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||||
|
filePath().toString(), m_project->qmakeVfs());
|
||||||
m_qmakeProFile->scheduleUpdate(QmakeProFile::ParseLater);
|
m_qmakeProFile->scheduleUpdate(QmakeProFile::ParseLater);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,11 +293,11 @@ static QStringList fileListForVar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QmakePriFile::extractSources(
|
void QmakePriFile::extractSources(
|
||||||
QHash<const ProFile *, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
|
QHash<int, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
|
||||||
QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type)
|
QVector<ProFileEvaluator::SourceFile> sourceFiles, FileType type)
|
||||||
{
|
{
|
||||||
foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) {
|
foreach (const ProFileEvaluator::SourceFile &source, sourceFiles) {
|
||||||
QmakePriFileEvalResult *result = proToResult.value(source.proFile);
|
auto *result = proToResult.value(source.proFileId);
|
||||||
if (!result)
|
if (!result)
|
||||||
result = fallback;
|
result = fallback;
|
||||||
result->foundFiles[type].insert(FileName::fromString(source.fileName));
|
result->foundFiles[type].insert(FileName::fromString(source.fileName));
|
||||||
@@ -304,12 +305,12 @@ void QmakePriFile::extractSources(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void QmakePriFile::extractInstalls(
|
void QmakePriFile::extractInstalls(
|
||||||
QHash<const ProFile *, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
|
QHash<int, QmakePriFileEvalResult *> proToResult, QmakePriFileEvalResult *fallback,
|
||||||
const InstallsList &installList)
|
const InstallsList &installList)
|
||||||
{
|
{
|
||||||
for (const InstallsItem &item : installList.items) {
|
for (const InstallsItem &item : installList.items) {
|
||||||
for (const ProFileEvaluator::SourceFile &source : item.files) {
|
for (const ProFileEvaluator::SourceFile &source : item.files) {
|
||||||
auto *result = proToResult.value(source.proFile);
|
auto *result = proToResult.value(source.proFileId);
|
||||||
if (!result)
|
if (!result)
|
||||||
result = fallback;
|
result = fallback;
|
||||||
result->folders.insert(FileName::fromString(source.fileName));
|
result->folders.insert(FileName::fromString(source.fileName));
|
||||||
@@ -621,7 +622,8 @@ bool QmakePriFile::saveModifiedEditors()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// force instant reload of ourselves
|
// force instant reload of ourselves
|
||||||
QtSupport::ProFileCacheManager::instance()->discardFile(filePath().toString());
|
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||||
|
filePath().toString(), m_project->qmakeVfs());
|
||||||
QmakeProject::notifyChanged(filePath());
|
QmakeProject::notifyChanged(filePath());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -701,7 +703,7 @@ QPair<ProFile *, QStringList> QmakePriFile::readProFile(const QString &file)
|
|||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QtSupport::ProMessageHandler handler;
|
QtSupport::ProMessageHandler handler;
|
||||||
QMakeParser parser(nullptr, &vfs, &handler);
|
QMakeParser parser(nullptr, &vfs, &handler);
|
||||||
includeFile = parser.parsedProBlock(QStringRef(&contents), file, 1);
|
includeFile = parser.parsedProBlock(QStringRef(&contents), 0, file, 1);
|
||||||
}
|
}
|
||||||
return qMakePair(includeFile, lines);
|
return qMakePair(includeFile, lines);
|
||||||
}
|
}
|
||||||
@@ -738,7 +740,7 @@ bool QmakePriFile::renameFile(const QString &oldName,
|
|||||||
QMakeParser parser(nullptr, nullptr, nullptr);
|
QMakeParser parser(nullptr, nullptr, nullptr);
|
||||||
QString contents = lines.join(QLatin1Char('\n'));
|
QString contents = lines.join(QLatin1Char('\n'));
|
||||||
includeFile = parser.parsedProBlock(QStringRef(&contents),
|
includeFile = parser.parsedProBlock(QStringRef(&contents),
|
||||||
filePath().toString(), 1, QMakeParser::FullGrammar);
|
0, filePath().toString(), 1, QMakeParser::FullGrammar);
|
||||||
QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did.
|
QTC_ASSERT(includeFile, return false); // The file should still be valid after what we did.
|
||||||
|
|
||||||
ProWriter::addFiles(includeFile, &lines,
|
ProWriter::addFiles(includeFile, &lines,
|
||||||
@@ -1294,7 +1296,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
|
|||||||
result->includedFiles.proFile = pro;
|
result->includedFiles.proFile = pro;
|
||||||
result->includedFiles.name = input.projectFilePath;
|
result->includedFiles.name = input.projectFilePath;
|
||||||
|
|
||||||
QHash<const ProFile *, QmakePriFileEvalResult *> proToResult;
|
QHash<int, QmakePriFileEvalResult *> proToResult;
|
||||||
|
|
||||||
result->projectType
|
result->projectType
|
||||||
= proFileTemplateTypeToProjectType(
|
= proFileTemplateTypeToProjectType(
|
||||||
@@ -1332,7 +1334,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
|
|||||||
childTree->proFile = child;
|
childTree->proFile = child;
|
||||||
childTree->name = childName;
|
childTree->name = childName;
|
||||||
current->children.insert(childName, childTree);
|
current->children.insert(childName, childTree);
|
||||||
proToResult[child] = &childTree->result;
|
proToResult[child->id()] = &childTree->result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toBuild.append(current->children.values());
|
toBuild.append(current->children.values());
|
||||||
@@ -1368,7 +1370,7 @@ QmakeEvalResult *QmakeProFile::evaluate(const QmakeEvalInput &input)
|
|||||||
childTree->proFile = child;
|
childTree->proFile = child;
|
||||||
childTree->name = childName;
|
childTree->name = childName;
|
||||||
current->children.insert(childName, childTree);
|
current->children.insert(childName, childTree);
|
||||||
proToResult[child] = &childTree->result;
|
proToResult[child->id()] = &childTree->result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toBuild.append(current->children.values());
|
toBuild.append(current->children.values());
|
||||||
|
@@ -201,11 +201,11 @@ private:
|
|||||||
static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir);
|
static QStringList baseVPaths(QtSupport::ProFileReader *reader, const QString &projectDir, const QString &buildDir);
|
||||||
static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir);
|
static QStringList fullVPaths(const QStringList &baseVPaths, QtSupport::ProFileReader *reader, const QString &qmakeVariable, const QString &projectDir);
|
||||||
static void extractSources(
|
static void extractSources(
|
||||||
QHash<const ProFile *, Internal::QmakePriFileEvalResult *> proToResult,
|
QHash<int, Internal::QmakePriFileEvalResult *> proToResult,
|
||||||
Internal::QmakePriFileEvalResult *fallback,
|
Internal::QmakePriFileEvalResult *fallback,
|
||||||
QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type);
|
QVector<ProFileEvaluator::SourceFile> sourceFiles, ProjectExplorer::FileType type);
|
||||||
static void extractInstalls(
|
static void extractInstalls(
|
||||||
QHash<const ProFile *, Internal::QmakePriFileEvalResult *> proToResult,
|
QHash<int, Internal::QmakePriFileEvalResult *> proToResult,
|
||||||
Internal::QmakePriFileEvalResult *fallback,
|
Internal::QmakePriFileEvalResult *fallback,
|
||||||
const InstallsList &installList);
|
const InstallsList &installList);
|
||||||
static void processValues(Internal::QmakePriFileEvalResult &result);
|
static void processValues(Internal::QmakePriFileEvalResult &result);
|
||||||
|
@@ -372,12 +372,14 @@ void QmakeProject::updateQmlJSCodeModel()
|
|||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
foreach (const QString &rc, exactResources) {
|
foreach (const QString &rc, exactResources) {
|
||||||
QString contents;
|
QString contents;
|
||||||
if (m_qmakeVfs->readFile(rc, QMakeVfs::VfsExact, &contents, &errorMessage) == QMakeVfs::ReadOk)
|
int id = m_qmakeVfs->idForFileName(rc, QMakeVfs::VfsExact);
|
||||||
|
if (m_qmakeVfs->readFile(id, &contents, &errorMessage) == QMakeVfs::ReadOk)
|
||||||
projectInfo.resourceFileContents[rc] = contents;
|
projectInfo.resourceFileContents[rc] = contents;
|
||||||
}
|
}
|
||||||
foreach (const QString &rc, cumulativeResources) {
|
foreach (const QString &rc, cumulativeResources) {
|
||||||
QString contents;
|
QString contents;
|
||||||
if (m_qmakeVfs->readFile(rc, QMakeVfs::VfsCumulative, &contents, &errorMessage) == QMakeVfs::ReadOk)
|
int id = m_qmakeVfs->idForFileName(rc, QMakeVfs::VfsCumulative);
|
||||||
|
if (m_qmakeVfs->readFile(id, &contents, &errorMessage) == QMakeVfs::ReadOk)
|
||||||
projectInfo.resourceFileContents[rc] = contents;
|
projectInfo.resourceFileContents[rc] = contents;
|
||||||
}
|
}
|
||||||
if (!hasQmlLib) {
|
if (!hasQmlLib) {
|
||||||
@@ -734,7 +736,7 @@ void QmakeProject::destroyProFileReader(QtSupport::ProFileReader *reader)
|
|||||||
QString dir = projectFilePath().toString();
|
QString dir = projectFilePath().toString();
|
||||||
if (!dir.endsWith(QLatin1Char('/')))
|
if (!dir.endsWith(QLatin1Char('/')))
|
||||||
dir += QLatin1Char('/');
|
dir += QLatin1Char('/');
|
||||||
QtSupport::ProFileCacheManager::instance()->discardFiles(dir);
|
QtSupport::ProFileCacheManager::instance()->discardFiles(dir, qmakeVfs());
|
||||||
QtSupport::ProFileCacheManager::instance()->decRefCount();
|
QtSupport::ProFileCacheManager::instance()->decRefCount();
|
||||||
|
|
||||||
m_qmakeGlobals.reset();
|
m_qmakeGlobals.reset();
|
||||||
@@ -842,7 +844,8 @@ void QmakeProject::setAllBuildConfigurationsEnabled(bool enabled)
|
|||||||
static void notifyChangedHelper(const FileName &fileName, QmakeProFile *file)
|
static void notifyChangedHelper(const FileName &fileName, QmakeProFile *file)
|
||||||
{
|
{
|
||||||
if (file->filePath() == fileName) {
|
if (file->filePath() == fileName) {
|
||||||
QtSupport::ProFileCacheManager::instance()->discardFile(fileName.toString());
|
QtSupport::ProFileCacheManager::instance()->discardFile(
|
||||||
|
fileName.toString(), file->project()->qmakeVfs());
|
||||||
file->scheduleUpdate(QmakeProFile::ParseNow);
|
file->scheduleUpdate(QmakeProFile::ParseNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,6 +36,8 @@
|
|||||||
#include <qmljseditor/qmljseditorconstants.h>
|
#include <qmljseditor/qmljseditorconstants.h>
|
||||||
#include <qmljstools/qmljstoolsconstants.h>
|
#include <qmljstools/qmljstoolsconstants.h>
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
@@ -62,12 +64,14 @@ SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
|
|||||||
m_ui.designerShowDebuggerCheckBox->setChecked(true);
|
m_ui.designerShowDebuggerCheckBox->setChecked(true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
m_ui.resetFallbackPuppetPathButton->hide();
|
|
||||||
connect(m_ui.resetFallbackPuppetPathButton, &QPushButton::clicked, [=]() {
|
connect(m_ui.resetFallbackPuppetPathButton, &QPushButton::clicked, [=]() {
|
||||||
m_ui.fallbackPuppetPathLineEdit->setPath(
|
m_ui.fallbackPuppetPathLineEdit->setPath(
|
||||||
PuppetCreator::defaultPuppetFallbackDirectory());
|
PuppetCreator::defaultPuppetFallbackDirectory());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
m_ui.fallbackPuppetPathLineEdit->setPath(PuppetCreator::defaultPuppetFallbackDirectory());
|
||||||
|
m_ui.fallbackPuppetPathLineEdit->lineEdit()->setPlaceholderText(PuppetCreator::defaultPuppetFallbackDirectory());
|
||||||
|
|
||||||
connect(m_ui.resetQmlPuppetBuildPathButton, &QPushButton::clicked, [=]() {
|
connect(m_ui.resetQmlPuppetBuildPathButton, &QPushButton::clicked, [=]() {
|
||||||
m_ui.puppetBuildPathLineEdit->setPath(
|
m_ui.puppetBuildPathLineEdit->setPath(
|
||||||
PuppetCreator::defaultPuppetToplevelBuildDirectory());
|
PuppetCreator::defaultPuppetToplevelBuildDirectory());
|
||||||
@@ -129,10 +133,16 @@ DesignerSettings SettingsPageWidget::settings() const
|
|||||||
settings.insert(DesignerSettingsKey::DEBUG_PUPPET,
|
settings.insert(DesignerSettingsKey::DEBUG_PUPPET,
|
||||||
m_ui.debugPuppetComboBox->currentText());
|
m_ui.debugPuppetComboBox->currentText());
|
||||||
|
|
||||||
if (!m_ui.fallbackPuppetPathLineEdit->path().isEmpty() &&
|
QString newFallbackPuppetPath = m_ui.fallbackPuppetPathLineEdit->path();
|
||||||
m_ui.fallbackPuppetPathLineEdit->path() != PuppetCreator::defaultPuppetFallbackDirectory()) {
|
QTC_CHECK(PuppetCreator::defaultPuppetFallbackDirectory() ==
|
||||||
|
m_ui.fallbackPuppetPathLineEdit->lineEdit()->placeholderText());
|
||||||
|
if (newFallbackPuppetPath.isEmpty())
|
||||||
|
newFallbackPuppetPath = m_ui.fallbackPuppetPathLineEdit->lineEdit()->placeholderText();
|
||||||
|
QString oldFallbackPuppetPath = settings.value(DesignerSettingsKey::PUPPET_FALLBACK_DIRECTORY,
|
||||||
|
PuppetCreator::defaultPuppetFallbackDirectory()).toString();
|
||||||
|
if (oldFallbackPuppetPath != newFallbackPuppetPath) {
|
||||||
settings.insert(DesignerSettingsKey::PUPPET_FALLBACK_DIRECTORY,
|
settings.insert(DesignerSettingsKey::PUPPET_FALLBACK_DIRECTORY,
|
||||||
m_ui.fallbackPuppetPathLineEdit->path());
|
newFallbackPuppetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_ui.puppetBuildPathLineEdit->path().isEmpty() &&
|
if (!m_ui.puppetBuildPathLineEdit->path().isEmpty() &&
|
||||||
|
@@ -312,8 +312,7 @@ void ExamplesListModel::parseExamples(QXmlStreamReader *reader,
|
|||||||
item.projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
item.projectPath = attributes.value(QLatin1String("projectPath")).toString();
|
||||||
item.hasSourceCode = !item.projectPath.isEmpty();
|
item.hasSourceCode = !item.projectPath.isEmpty();
|
||||||
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, examplesInstallPath);
|
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, examplesInstallPath);
|
||||||
item.imageUrl = Utils::StyleHelper::dpiSpecificImageFile(
|
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||||
attributes.value(QLatin1String("imageUrl")).toString());
|
|
||||||
QPixmapCache::remove(item.imageUrl);
|
QPixmapCache::remove(item.imageUrl);
|
||||||
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||||
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
||||||
@@ -412,7 +411,8 @@ void ExamplesListModel::parseTutorials(QXmlStreamReader *reader, const QString &
|
|||||||
item.hasSourceCode = !item.projectPath.isEmpty();
|
item.hasSourceCode = !item.projectPath.isEmpty();
|
||||||
item.projectPath.prepend(slash);
|
item.projectPath.prepend(slash);
|
||||||
item.projectPath.prepend(projectsOffset);
|
item.projectPath.prepend(projectsOffset);
|
||||||
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
item.imageUrl = Utils::StyleHelper::dpiSpecificImageFile(
|
||||||
|
attributes.value(QLatin1String("imageUrl")).toString());
|
||||||
QPixmapCache::remove(item.imageUrl);
|
QPixmapCache::remove(item.imageUrl);
|
||||||
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||||
item.isVideo = attributes.value(QLatin1String("isVideo")).toString() == QLatin1String("true");
|
item.isVideo = attributes.value(QLatin1String("isVideo")).toString() == QLatin1String("true");
|
||||||
|
@@ -413,7 +413,8 @@ public:
|
|||||||
QRect pixmapRect = inner;
|
QRect pixmapRect = inner;
|
||||||
if (!pm.isNull()) {
|
if (!pm.isNull()) {
|
||||||
painter->setPen(foregroundColor2);
|
painter->setPen(foregroundColor2);
|
||||||
pixmapRect = inner.adjusted(6, 20, -6, -15);
|
if (!m_showExamples)
|
||||||
|
pixmapRect = inner.adjusted(6, 20, -6, -15);
|
||||||
QPoint pixmapPos = pixmapRect.center();
|
QPoint pixmapPos = pixmapRect.center();
|
||||||
pixmapPos.rx() -= pm.width() / pm.devicePixelRatio() / 2;
|
pixmapPos.rx() -= pm.width() / pm.devicePixelRatio() / 2;
|
||||||
pixmapPos.ry() -= pm.height() / pm.devicePixelRatio() / 2;
|
pixmapPos.ry() -= pm.height() / pm.devicePixelRatio() / 2;
|
||||||
@@ -533,6 +534,8 @@ public:
|
|||||||
return QAbstractItemDelegate::editorEvent(ev, model, option, idx);
|
return QAbstractItemDelegate::editorEvent(ev, model, option, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setShowExamples(bool showExamples) { m_showExamples = showExamples; goon(); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void tagClicked(const QString &tag);
|
void tagClicked(const QString &tag);
|
||||||
|
|
||||||
@@ -547,6 +550,7 @@ private:
|
|||||||
mutable QRect m_currentArea;
|
mutable QRect m_currentArea;
|
||||||
mutable QPointer<QAbstractItemView> m_currentWidget;
|
mutable QPointer<QAbstractItemView> m_currentWidget;
|
||||||
mutable QVector<QPair<QString, QRect>> m_currentTagRects;
|
mutable QVector<QPair<QString, QRect>> m_currentTagRects;
|
||||||
|
bool m_showExamples = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExamplesPageWidget : public QWidget
|
class ExamplesPageWidget : public QWidget
|
||||||
@@ -555,6 +559,7 @@ public:
|
|||||||
ExamplesPageWidget(bool isExamples)
|
ExamplesPageWidget(bool isExamples)
|
||||||
: m_isExamples(isExamples)
|
: m_isExamples(isExamples)
|
||||||
{
|
{
|
||||||
|
m_exampleDelegate.setShowExamples(isExamples);
|
||||||
const int sideMargin = 27;
|
const int sideMargin = 27;
|
||||||
static ExamplesListModel *s_examplesModel = new ExamplesListModel(this);
|
static ExamplesListModel *s_examplesModel = new ExamplesListModel(this);
|
||||||
m_examplesModel = s_examplesModel;
|
m_examplesModel = s_examplesModel;
|
||||||
|
@@ -166,16 +166,17 @@ void ProFileCacheManager::clear()
|
|||||||
// loop is concerned. Use a shared pointer once this is not true anymore.
|
// loop is concerned. Use a shared pointer once this is not true anymore.
|
||||||
delete m_cache;
|
delete m_cache;
|
||||||
m_cache = 0;
|
m_cache = 0;
|
||||||
|
QMakeVfs::clearIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProFileCacheManager::discardFiles(const QString &prefix)
|
void ProFileCacheManager::discardFiles(const QString &prefix, QMakeVfs *vfs)
|
||||||
{
|
{
|
||||||
if (m_cache)
|
if (m_cache)
|
||||||
m_cache->discardFiles(prefix);
|
m_cache->discardFiles(prefix, vfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProFileCacheManager::discardFile(const QString &fileName)
|
void ProFileCacheManager::discardFile(const QString &fileName, QMakeVfs *vfs)
|
||||||
{
|
{
|
||||||
if (m_cache)
|
if (m_cache)
|
||||||
m_cache->discardFile(fileName);
|
m_cache->discardFile(fileName, vfs);
|
||||||
}
|
}
|
||||||
|
@@ -93,8 +93,8 @@ class QTSUPPORT_EXPORT ProFileCacheManager : public QObject
|
|||||||
public:
|
public:
|
||||||
static ProFileCacheManager *instance() { return s_instance; }
|
static ProFileCacheManager *instance() { return s_instance; }
|
||||||
ProFileCache *cache();
|
ProFileCache *cache();
|
||||||
void discardFiles(const QString &prefix);
|
void discardFiles(const QString &prefix, QMakeVfs *vfs);
|
||||||
void discardFile(const QString &fileName);
|
void discardFile(const QString &fileName, QMakeVfs *vfs);
|
||||||
void incRefCount();
|
void incRefCount();
|
||||||
void decRefCount();
|
void decRefCount();
|
||||||
|
|
||||||
|
@@ -66,6 +66,10 @@
|
|||||||
<description><![CDATA[Using Qt Creator tutorials and examples to develop Qt applications.]]></description>
|
<description><![CDATA[Using Qt Creator tutorials and examples to develop Qt applications.]]></description>
|
||||||
<tags>qt creator,video</tags>
|
<tags>qt creator,video</tags>
|
||||||
</tutorial>
|
</tutorial>
|
||||||
|
<tutorial imageUrl=":qtsupport/images/icons/videotutorialicon.png" difficulty="" projectPath="" name="Online: Qt Creator - Using Qt Quick Designer" isVideo="true" videoUrl="https://www.youtube.com/watch?v=0Po3tE9yUcU" videoLength="7:36">
|
||||||
|
<description><![CDATA[Using Qt Quick Designer to develop Qt Quick applications.]]></description>
|
||||||
|
<tags>qt creator,qt quick,video</tags>
|
||||||
|
</tutorial>
|
||||||
|
|
||||||
<tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Getting Started" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nGFmjOiT22Y" videoLength="50:36">
|
<tutorial imageUrl=":qtsupport/images/icons/qteventicon.png" difficulty="" projectPath="" name="Talk: Qt Creator - Getting Started" isVideo="true" videoUrl="https://www.youtube.com/watch?v=nGFmjOiT22Y" videoLength="50:36">
|
||||||
<description><![CDATA[Getting started with using Qt Creator for cross-platform development.]]></description>
|
<description><![CDATA[Getting started with using Qt Creator for cross-platform development.]]></description>
|
||||||
|
@@ -35,8 +35,13 @@
|
|||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
# include <utime.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define fL1S(s) QString::fromLatin1(s)
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace QMakeInternal;
|
using namespace QMakeInternal;
|
||||||
@@ -59,21 +64,22 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName)
|
|||||||
|
|
||||||
bool IoUtils::isRelativePath(const QString &path)
|
bool IoUtils::isRelativePath(const QString &path)
|
||||||
{
|
{
|
||||||
if (path.startsWith(QLatin1Char('/')))
|
|
||||||
return false;
|
|
||||||
#ifdef QMAKE_BUILTIN_PRFS
|
#ifdef QMAKE_BUILTIN_PRFS
|
||||||
if (path.startsWith(QLatin1String(":/")))
|
if (path.startsWith(QLatin1String(":/")))
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (path.startsWith(QLatin1Char('\\')))
|
// Unlike QFileInfo, this considers only paths with both a drive prefix and
|
||||||
return false;
|
// a subsequent (back-)slash absolute:
|
||||||
// Unlike QFileInfo, this won't accept a relative path with a drive letter.
|
|
||||||
// Such paths result in a royal mess anyway ...
|
|
||||||
if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter()
|
if (path.length() >= 3 && path.at(1) == QLatin1Char(':') && path.at(0).isLetter()
|
||||||
&& (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\')))
|
&& (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) {
|
||||||
return false;
|
return false;
|
||||||
#endif
|
}
|
||||||
|
// (... unless, of course, they're UNC, which qmake fails on anyway)
|
||||||
|
#else
|
||||||
|
if (path.startsWith(QLatin1Char('/')))
|
||||||
|
return false;
|
||||||
|
#endif // Q_OS_WIN
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +99,12 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName)
|
|||||||
return QString();
|
return QString();
|
||||||
if (isAbsolutePath(fileName))
|
if (isAbsolutePath(fileName))
|
||||||
return QDir::cleanPath(fileName);
|
return QDir::cleanPath(fileName);
|
||||||
|
#ifdef Q_OS_WIN // Add drive to otherwise-absolute path:
|
||||||
|
if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') {
|
||||||
|
Q_ASSERT(isAbsolutePath(baseDir));
|
||||||
|
return QDir::cleanPath(baseDir.left(2) + fileName);
|
||||||
|
}
|
||||||
|
#endif // Q_OS_WIN
|
||||||
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
|
return QDir::cleanPath(baseDir + QLatin1Char('/') + fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,4 +193,105 @@ QString IoUtils::shellQuoteWin(const QString &arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PROEVALUATOR_FULL)
|
||||||
|
|
||||||
|
# if defined(Q_OS_WIN)
|
||||||
|
static QString windowsErrorCode()
|
||||||
|
{
|
||||||
|
wchar_t *string = 0;
|
||||||
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
|
NULL,
|
||||||
|
GetLastError(),
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPWSTR)&string,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
QString ret = QString::fromWCharArray(string);
|
||||||
|
LocalFree((HLOCAL)string);
|
||||||
|
return ret.trimmed();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString)
|
||||||
|
{
|
||||||
|
# ifdef Q_OS_UNIX
|
||||||
|
struct stat st;
|
||||||
|
if (stat(referenceFileName.toLocal8Bit().constData(), &st)) {
|
||||||
|
*errorString = fL1S("Cannot stat() reference file %1: %2.").arg(referenceFileName, fL1S(strerror(errno)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
|
||||||
|
const struct timespec times[2] = { { 0, UTIME_NOW }, st.st_mtim };
|
||||||
|
const bool utimeError = utimensat(AT_FDCWD, targetFileName.toLocal8Bit().constData(), times, 0) < 0;
|
||||||
|
# else
|
||||||
|
struct utimbuf utb;
|
||||||
|
utb.actime = time(0);
|
||||||
|
utb.modtime = st.st_mtime;
|
||||||
|
const bool utimeError= utime(targetFileName.toLocal8Bit().constData(), &utb) < 0;
|
||||||
|
# endif
|
||||||
|
if (utimeError) {
|
||||||
|
*errorString = fL1S("Cannot touch %1: %2.").arg(targetFileName, fL1S(strerror(errno)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
HANDLE rHand = CreateFile((wchar_t*)referenceFileName.utf16(),
|
||||||
|
GENERIC_READ, FILE_SHARE_READ,
|
||||||
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (rHand == INVALID_HANDLE_VALUE) {
|
||||||
|
*errorString = fL1S("Cannot open reference file %1: %2").arg(referenceFileName, windowsErrorCode());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FILETIME ft;
|
||||||
|
GetFileTime(rHand, 0, 0, &ft);
|
||||||
|
CloseHandle(rHand);
|
||||||
|
HANDLE wHand = CreateFile((wchar_t*)targetFileName.utf16(),
|
||||||
|
GENERIC_WRITE, FILE_SHARE_READ,
|
||||||
|
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (wHand == INVALID_HANDLE_VALUE) {
|
||||||
|
*errorString = fL1S("Cannot open %1: %2").arg(targetFileName, windowsErrorCode());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SetFileTime(wHand, 0, 0, &ft);
|
||||||
|
CloseHandle(wHand);
|
||||||
|
# endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX)
|
||||||
|
bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target)
|
||||||
|
{
|
||||||
|
const QByteArray localSymlinkPath = QFile::encodeName(symlinkPath);
|
||||||
|
# if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||||
|
# define PATH_CHUNK_SIZE 256
|
||||||
|
char *s = 0;
|
||||||
|
int len = -1;
|
||||||
|
int size = PATH_CHUNK_SIZE;
|
||||||
|
|
||||||
|
forever {
|
||||||
|
s = (char *)::realloc(s, size);
|
||||||
|
len = ::readlink(localSymlinkPath.constData(), s, size);
|
||||||
|
if (len < 0) {
|
||||||
|
::free(s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (len < size)
|
||||||
|
break;
|
||||||
|
size *= 2;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
char s[PATH_MAX+1];
|
||||||
|
int len = readlink(localSymlinkPath.constData(), s, PATH_MAX);
|
||||||
|
# endif
|
||||||
|
if (len <= 0)
|
||||||
|
return false;
|
||||||
|
*target = QFile::decodeName(QByteArray(s, len));
|
||||||
|
# if defined(__GLIBC__) && !defined(PATH_MAX)
|
||||||
|
::free(s);
|
||||||
|
# endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // PROEVALUATOR_FULL
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@@ -60,6 +60,12 @@ public:
|
|||||||
#else
|
#else
|
||||||
{ return shellQuoteWin(arg); }
|
{ return shellQuoteWin(arg); }
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(PROEVALUATOR_FULL)
|
||||||
|
static bool touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString);
|
||||||
|
# if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX)
|
||||||
|
static bool readLinkTarget(const QString &symlinkPath, QString *target);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ProFileEvaluatorInternal
|
} // namespace ProFileEvaluatorInternal
|
||||||
|
@@ -196,13 +196,15 @@ QVector<ProFileEvaluator::SourceFile> ProFileEvaluator::absoluteFileValues(
|
|||||||
|
|
||||||
ProFileEvaluator::TemplateType ProFileEvaluator::templateType() const
|
ProFileEvaluator::TemplateType ProFileEvaluator::templateType() const
|
||||||
{
|
{
|
||||||
|
static QString str_staticlib = QStringLiteral("staticlib");
|
||||||
|
|
||||||
const ProStringList &templ = d->values(ProKey("TEMPLATE"));
|
const ProStringList &templ = d->values(ProKey("TEMPLATE"));
|
||||||
if (templ.count() >= 1) {
|
if (templ.count() >= 1) {
|
||||||
const QString &t = templ.at(0).toQString();
|
const QString &t = templ.at(0).toQString();
|
||||||
if (!t.compare(QLatin1String("app"), Qt::CaseInsensitive))
|
if (!t.compare(QLatin1String("app"), Qt::CaseInsensitive))
|
||||||
return TT_Application;
|
return TT_Application;
|
||||||
if (!t.compare(QLatin1String("lib"), Qt::CaseInsensitive))
|
if (!t.compare(QLatin1String("lib"), Qt::CaseInsensitive))
|
||||||
return d->isActiveConfig(QStringLiteral("staticlib")) ? TT_StaticLibrary : TT_SharedLibrary;
|
return d->isActiveConfig(QStringRef(&str_staticlib)) ? TT_StaticLibrary : TT_SharedLibrary;
|
||||||
if (!t.compare(QLatin1String("script"), Qt::CaseInsensitive))
|
if (!t.compare(QLatin1String("script"), Qt::CaseInsensitive))
|
||||||
return TT_Script;
|
return TT_Script;
|
||||||
if (!t.compare(QLatin1String("aux"), Qt::CaseInsensitive))
|
if (!t.compare(QLatin1String("aux"), Qt::CaseInsensitive))
|
||||||
@@ -224,6 +226,10 @@ bool ProFileEvaluator::loadNamedSpec(const QString &specDir, bool hostSpec)
|
|||||||
|
|
||||||
bool ProFileEvaluator::accept(ProFile *pro, QMakeEvaluator::LoadFlags flags)
|
bool ProFileEvaluator::accept(ProFile *pro, QMakeEvaluator::LoadFlags flags)
|
||||||
{
|
{
|
||||||
|
static QString str_no_include_pwd = QStringLiteral("no_include_pwd");
|
||||||
|
static QString str_plugin = QStringLiteral("plugin");
|
||||||
|
static QString str_plugin_no_share_shlib_cflags = QStringLiteral("plugin_no_share_shlib_cflags");
|
||||||
|
|
||||||
if (d->visitProFile(pro, QMakeHandler::EvalProjectFile, flags) != QMakeEvaluator::ReturnTrue)
|
if (d->visitProFile(pro, QMakeHandler::EvalProjectFile, flags) != QMakeEvaluator::ReturnTrue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -232,7 +238,7 @@ bool ProFileEvaluator::accept(ProFile *pro, QMakeEvaluator::LoadFlags flags)
|
|||||||
|
|
||||||
ProStringList &incpath = d->valuesRef(ProKey("INCLUDEPATH"));
|
ProStringList &incpath = d->valuesRef(ProKey("INCLUDEPATH"));
|
||||||
incpath += d->values(ProKey("QMAKE_INCDIR"));
|
incpath += d->values(ProKey("QMAKE_INCDIR"));
|
||||||
if (!d->isActiveConfig(QStringLiteral("no_include_pwd"))) {
|
if (!d->isActiveConfig(QStringRef(&str_no_include_pwd))) {
|
||||||
incpath.prepend(ProString(pro->directoryName()));
|
incpath.prepend(ProString(pro->directoryName()));
|
||||||
// It's pretty stupid that this is appended - it should be the second entry.
|
// It's pretty stupid that this is appended - it should be the second entry.
|
||||||
if (pro->directoryName() != d->m_outputDir)
|
if (pro->directoryName() != d->m_outputDir)
|
||||||
@@ -249,8 +255,8 @@ bool ProFileEvaluator::accept(ProFile *pro, QMakeEvaluator::LoadFlags flags)
|
|||||||
break;
|
break;
|
||||||
case TT_SharedLibrary:
|
case TT_SharedLibrary:
|
||||||
{
|
{
|
||||||
bool plugin = d->isActiveConfig(QStringLiteral("plugin"));
|
bool plugin = d->isActiveConfig(QStringRef(&str_plugin));
|
||||||
if (!plugin || !d->isActiveConfig(QStringLiteral("plugin_no_share_shlib_cflags")))
|
if (!plugin || !d->isActiveConfig(QStringRef(&str_plugin_no_share_shlib_cflags)))
|
||||||
cxxflags += d->values(ProKey("QMAKE_CXXFLAGS_SHLIB"));
|
cxxflags += d->values(ProKey("QMAKE_CXXFLAGS_SHLIB"));
|
||||||
if (plugin)
|
if (plugin)
|
||||||
cxxflags += d->values(ProKey("QMAKE_CXXFLAGS_PLUGIN"));
|
cxxflags += d->values(ProKey("QMAKE_CXXFLAGS_PLUGIN"));
|
||||||
|
@@ -55,7 +55,7 @@ public:
|
|||||||
|
|
||||||
struct SourceFile {
|
struct SourceFile {
|
||||||
QString fileName;
|
QString fileName;
|
||||||
const ProFile *proFile;
|
int proFileId;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call this from a concurrency-free context
|
// Call this from a concurrency-free context
|
||||||
|
@@ -71,6 +71,11 @@ ProString::ProString(const QString &str) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProString::ProString(const QStringRef &str) :
|
||||||
|
m_string(*str.string()), m_offset(str.position()), m_length(str.size()), m_file(0), m_hash(0x80000000)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ProString::ProString(const char *str, DoPreHashing) :
|
ProString::ProString(const char *str, DoPreHashing) :
|
||||||
m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0)
|
m_string(QString::fromLatin1(str)), m_offset(0), m_length(qstrlen(str)), m_file(0)
|
||||||
{
|
{
|
||||||
@@ -333,7 +338,7 @@ ProString ProString::trimmed() const
|
|||||||
|
|
||||||
QTextStream &operator<<(QTextStream &t, const ProString &str)
|
QTextStream &operator<<(QTextStream &t, const ProString &str)
|
||||||
{
|
{
|
||||||
t << str.toQString(); // XXX optimize ... somehow
|
t << str.toQStringRef();
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,9 +398,12 @@ void ProStringList::removeAll(const char *str)
|
|||||||
|
|
||||||
void ProStringList::removeEach(const ProStringList &value)
|
void ProStringList::removeEach(const ProStringList &value)
|
||||||
{
|
{
|
||||||
for (const ProString &str : value)
|
for (const ProString &str : value) {
|
||||||
|
if (isEmpty())
|
||||||
|
break;
|
||||||
if (!str.isEmpty())
|
if (!str.isEmpty())
|
||||||
removeAll(str);
|
removeAll(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProStringList::removeEmpty()
|
void ProStringList::removeEmpty()
|
||||||
@@ -455,6 +463,14 @@ bool ProStringList::contains(const ProString &str, Qt::CaseSensitivity cs) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProStringList::contains(const QStringRef &str, Qt::CaseSensitivity cs) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < size(); i++)
|
||||||
|
if (!at(i).toQStringRef().compare(str, cs))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const
|
bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < size(); i++)
|
for (int i = 0; i < size(); i++)
|
||||||
@@ -463,9 +479,10 @@ bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFile::ProFile(const QString &fileName)
|
ProFile::ProFile(int id, const QString &fileName)
|
||||||
: m_refCount(1),
|
: m_refCount(1),
|
||||||
m_fileName(fileName),
|
m_fileName(fileName),
|
||||||
|
m_id(id),
|
||||||
m_ok(true),
|
m_ok(true),
|
||||||
m_hostBuild(false)
|
m_hostBuild(false)
|
||||||
{
|
{
|
||||||
@@ -482,7 +499,7 @@ ProString ProFile::getStr(const ushort *&tPtr)
|
|||||||
{
|
{
|
||||||
uint len = *tPtr++;
|
uint len = *tPtr++;
|
||||||
ProString ret(items(), tPtr - tokPtr(), len);
|
ProString ret(items(), tPtr - tokPtr(), len);
|
||||||
ret.setSource(this);
|
ret.setSource(m_id);
|
||||||
tPtr += len;
|
tPtr += len;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -64,13 +64,14 @@ public:
|
|||||||
ProString();
|
ProString();
|
||||||
ProString(const ProString &other);
|
ProString(const ProString &other);
|
||||||
PROITEM_EXPLICIT ProString(const QString &str);
|
PROITEM_EXPLICIT ProString(const QString &str);
|
||||||
|
PROITEM_EXPLICIT ProString(const QStringRef &str);
|
||||||
PROITEM_EXPLICIT ProString(const char *str);
|
PROITEM_EXPLICIT ProString(const char *str);
|
||||||
ProString(const QString &str, int offset, int length);
|
ProString(const QString &str, int offset, int length);
|
||||||
void setValue(const QString &str);
|
void setValue(const QString &str);
|
||||||
void clear() { m_string.clear(); m_length = 0; }
|
void clear() { m_string.clear(); m_length = 0; }
|
||||||
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
|
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
|
||||||
ProString &setSource(const ProFile *pro) { m_file = pro; return *this; }
|
ProString &setSource(int id) { m_file = id; return *this; }
|
||||||
const ProFile *sourceFile() const { return m_file; }
|
int sourceFile() const { return m_file; }
|
||||||
|
|
||||||
ProString &prepend(const ProString &other);
|
ProString &prepend(const ProString &other);
|
||||||
ProString &append(const ProString &other, bool *pending = 0);
|
ProString &append(const ProString &other, bool *pending = 0);
|
||||||
@@ -90,6 +91,7 @@ public:
|
|||||||
|
|
||||||
bool operator==(const ProString &other) const { return toQStringRef() == other.toQStringRef(); }
|
bool operator==(const ProString &other) const { return toQStringRef() == other.toQStringRef(); }
|
||||||
bool operator==(const QString &other) const { return toQStringRef() == other; }
|
bool operator==(const QString &other) const { return toQStringRef() == other; }
|
||||||
|
bool operator==(const QStringRef &other) const { return toQStringRef() == other; }
|
||||||
bool operator==(QLatin1String other) const { return toQStringRef() == other; }
|
bool operator==(QLatin1String other) const { return toQStringRef() == other; }
|
||||||
bool operator==(const char *other) const { return toQStringRef() == QLatin1String(other); }
|
bool operator==(const char *other) const { return toQStringRef() == QLatin1String(other); }
|
||||||
bool operator!=(const ProString &other) const { return !(*this == other); }
|
bool operator!=(const ProString &other) const { return !(*this == other); }
|
||||||
@@ -159,7 +161,7 @@ private:
|
|||||||
|
|
||||||
QString m_string;
|
QString m_string;
|
||||||
int m_offset, m_length;
|
int m_offset, m_length;
|
||||||
const ProFile *m_file;
|
int m_file;
|
||||||
mutable uint m_hash;
|
mutable uint m_hash;
|
||||||
QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
|
QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
|
||||||
uint updatedHash() const;
|
uint updatedHash() const;
|
||||||
@@ -199,14 +201,14 @@ Q_DECLARE_TYPEINFO(ProKey, Q_MOVABLE_TYPE);
|
|||||||
uint qHash(const ProString &str);
|
uint qHash(const ProString &str);
|
||||||
QString operator+(const ProString &one, const ProString &two);
|
QString operator+(const ProString &one, const ProString &two);
|
||||||
inline QString operator+(const ProString &one, const QString &two)
|
inline QString operator+(const ProString &one, const QString &two)
|
||||||
{ return one + ProString(two); }
|
{ return one.toQStringRef() + two; }
|
||||||
inline QString operator+(const QString &one, const ProString &two)
|
inline QString operator+(const QString &one, const ProString &two)
|
||||||
{ return ProString(one) + two; }
|
{ return one + two.toQStringRef(); }
|
||||||
|
|
||||||
inline QString operator+(const ProString &one, const char *two)
|
inline QString operator+(const ProString &one, const char *two)
|
||||||
{ return one + ProString(two); } // XXX optimize
|
{ return one.toQStringRef() + QLatin1String(two); }
|
||||||
inline QString operator+(const char *one, const ProString &two)
|
inline QString operator+(const char *one, const ProString &two)
|
||||||
{ return ProString(one) + two; } // XXX optimize
|
{ return QLatin1String(one) + two.toQStringRef(); }
|
||||||
|
|
||||||
inline QString &operator+=(QString &that, const ProString &other)
|
inline QString &operator+=(QString &that, const ProString &other)
|
||||||
{ return that += other.toQStringRef(); }
|
{ return that += other.toQStringRef(); }
|
||||||
@@ -244,6 +246,7 @@ public:
|
|||||||
void removeDuplicates();
|
void removeDuplicates();
|
||||||
|
|
||||||
bool contains(const ProString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
bool contains(const ProString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||||
|
bool contains(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||||
bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
|
bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
|
||||||
{ return contains(ProString(str), cs); }
|
{ return contains(ProString(str), cs); }
|
||||||
bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
bool contains(const char *str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
|
||||||
@@ -320,6 +323,9 @@ enum ProToken {
|
|||||||
// - function name: hash (2), length (1), chars (length)
|
// - function name: hash (2), length (1), chars (length)
|
||||||
// - body length (2)
|
// - body length (2)
|
||||||
// - body + TokTerminator (body length)
|
// - body + TokTerminator (body length)
|
||||||
|
TokBypassNesting, // escape from function local variable scopes:
|
||||||
|
// - block length (2)
|
||||||
|
// - block + TokTerminator (block length)
|
||||||
TokMask = 0xff,
|
TokMask = 0xff,
|
||||||
TokQuoted = 0x100, // The expression is quoted => join expanded stringlist
|
TokQuoted = 0x100, // The expression is quoted => join expanded stringlist
|
||||||
TokNewStr = 0x200 // Next stringlist element
|
TokNewStr = 0x200 // Next stringlist element
|
||||||
@@ -328,9 +334,10 @@ enum ProToken {
|
|||||||
class QMAKE_EXPORT ProFile
|
class QMAKE_EXPORT ProFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ProFile(const QString &fileName);
|
ProFile(int id, const QString &fileName);
|
||||||
~ProFile();
|
~ProFile();
|
||||||
|
|
||||||
|
int id() const { return m_id; }
|
||||||
QString fileName() const { return m_fileName; }
|
QString fileName() const { return m_fileName; }
|
||||||
QString directoryName() const { return m_directoryName; }
|
QString directoryName() const { return m_directoryName; }
|
||||||
const QString &items() const { return m_proitems; }
|
const QString &items() const { return m_proitems; }
|
||||||
@@ -355,6 +362,7 @@ private:
|
|||||||
QString m_proitems;
|
QString m_proitems;
|
||||||
QString m_fileName;
|
QString m_fileName;
|
||||||
QString m_directoryName;
|
QString m_directoryName;
|
||||||
|
int m_id;
|
||||||
bool m_ok;
|
bool m_ok;
|
||||||
bool m_hostBuild;
|
bool m_hostBuild;
|
||||||
};
|
};
|
||||||
|
@@ -176,7 +176,7 @@ QString ProWriter::compileScope(const QString &scope)
|
|||||||
if (scope.isEmpty())
|
if (scope.isEmpty())
|
||||||
return QString();
|
return QString();
|
||||||
QMakeParser parser(0, 0, 0);
|
QMakeParser parser(0, 0, 0);
|
||||||
ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), QLatin1String("no-file"), 1);
|
ProFile *includeFile = parser.parsedProBlock(QStringRef(&scope), 0, QLatin1String("no-file"), 1);
|
||||||
if (!includeFile)
|
if (!includeFile)
|
||||||
return QString();
|
return QString();
|
||||||
QString result = includeFile->items();
|
QString result = includeFile->items();
|
||||||
|
@@ -52,7 +52,6 @@
|
|||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <utime.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -98,7 +97,7 @@ enum TestFunc {
|
|||||||
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
|
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
|
||||||
T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE,
|
T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE,
|
||||||
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
|
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
|
||||||
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
|
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE, T_RELOAD_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
void QMakeEvaluator::initFunctionStatics()
|
void QMakeEvaluator::initFunctionStatics()
|
||||||
@@ -107,53 +106,53 @@ void QMakeEvaluator::initFunctionStatics()
|
|||||||
const char * const name;
|
const char * const name;
|
||||||
const ExpandFunc func;
|
const ExpandFunc func;
|
||||||
} expandInits[] = {
|
} expandInits[] = {
|
||||||
{"member", E_MEMBER},
|
{ "member", E_MEMBER },
|
||||||
{"str_member", E_STR_MEMBER},
|
{ "str_member", E_STR_MEMBER },
|
||||||
{"first", E_FIRST},
|
{ "first", E_FIRST },
|
||||||
{"take_first", E_TAKE_FIRST},
|
{ "take_first", E_TAKE_FIRST },
|
||||||
{"last", E_LAST},
|
{ "last", E_LAST },
|
||||||
{"take_last", E_TAKE_LAST},
|
{ "take_last", E_TAKE_LAST },
|
||||||
{"size", E_SIZE},
|
{ "size", E_SIZE },
|
||||||
{"str_size", E_STR_SIZE},
|
{ "str_size", E_STR_SIZE },
|
||||||
{"cat", E_CAT},
|
{ "cat", E_CAT },
|
||||||
{"fromfile", E_FROMFILE},
|
{ "fromfile", E_FROMFILE },
|
||||||
{"eval", E_EVAL},
|
{ "eval", E_EVAL },
|
||||||
{"list", E_LIST},
|
{ "list", E_LIST },
|
||||||
{"sprintf", E_SPRINTF},
|
{ "sprintf", E_SPRINTF },
|
||||||
{"format_number", E_FORMAT_NUMBER},
|
{ "format_number", E_FORMAT_NUMBER },
|
||||||
{"num_add", E_NUM_ADD},
|
{ "num_add", E_NUM_ADD },
|
||||||
{"join", E_JOIN},
|
{ "join", E_JOIN },
|
||||||
{"split", E_SPLIT},
|
{ "split", E_SPLIT },
|
||||||
{"basename", E_BASENAME},
|
{ "basename", E_BASENAME },
|
||||||
{"dirname", E_DIRNAME},
|
{ "dirname", E_DIRNAME },
|
||||||
{"section", E_SECTION},
|
{ "section", E_SECTION },
|
||||||
{"find", E_FIND},
|
{ "find", E_FIND },
|
||||||
{"system", E_SYSTEM},
|
{ "system", E_SYSTEM },
|
||||||
{"unique", E_UNIQUE},
|
{ "unique", E_UNIQUE },
|
||||||
{"sorted", E_SORTED},
|
{ "sorted", E_SORTED },
|
||||||
{"reverse", E_REVERSE},
|
{ "reverse", E_REVERSE },
|
||||||
{"quote", E_QUOTE},
|
{ "quote", E_QUOTE },
|
||||||
{"escape_expand", E_ESCAPE_EXPAND},
|
{ "escape_expand", E_ESCAPE_EXPAND },
|
||||||
{"upper", E_UPPER},
|
{ "upper", E_UPPER },
|
||||||
{"lower", E_LOWER},
|
{ "lower", E_LOWER },
|
||||||
{"title", E_TITLE},
|
{ "title", E_TITLE },
|
||||||
{"re_escape", E_RE_ESCAPE},
|
{ "re_escape", E_RE_ESCAPE },
|
||||||
{"val_escape", E_VAL_ESCAPE},
|
{ "val_escape", E_VAL_ESCAPE },
|
||||||
{"files", E_FILES},
|
{ "files", E_FILES },
|
||||||
{"prompt", E_PROMPT},
|
{ "prompt", E_PROMPT },
|
||||||
{"replace", E_REPLACE},
|
{ "replace", E_REPLACE },
|
||||||
{"sort_depends", E_SORT_DEPENDS},
|
{ "sort_depends", E_SORT_DEPENDS },
|
||||||
{"resolve_depends", E_RESOLVE_DEPENDS},
|
{ "resolve_depends", E_RESOLVE_DEPENDS },
|
||||||
{"enumerate_vars", E_ENUMERATE_VARS},
|
{ "enumerate_vars", E_ENUMERATE_VARS },
|
||||||
{"shadowed", E_SHADOWED},
|
{ "shadowed", E_SHADOWED },
|
||||||
{"absolute_path", E_ABSOLUTE_PATH},
|
{ "absolute_path", E_ABSOLUTE_PATH },
|
||||||
{"relative_path", E_RELATIVE_PATH},
|
{ "relative_path", E_RELATIVE_PATH },
|
||||||
{"clean_path", E_CLEAN_PATH},
|
{ "clean_path", E_CLEAN_PATH },
|
||||||
{"system_path", E_SYSTEM_PATH},
|
{ "system_path", E_SYSTEM_PATH },
|
||||||
{"shell_path", E_SHELL_PATH},
|
{ "shell_path", E_SHELL_PATH },
|
||||||
{"system_quote", E_SYSTEM_QUOTE},
|
{ "system_quote", E_SYSTEM_QUOTE },
|
||||||
{"shell_quote", E_SHELL_QUOTE},
|
{ "shell_quote", E_SHELL_QUOTE },
|
||||||
{"getenv", E_GETENV},
|
{ "getenv", E_GETENV },
|
||||||
};
|
};
|
||||||
statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
|
statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
|
||||||
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
|
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
|
||||||
@@ -163,40 +162,41 @@ void QMakeEvaluator::initFunctionStatics()
|
|||||||
const char * const name;
|
const char * const name;
|
||||||
const TestFunc func;
|
const TestFunc func;
|
||||||
} testInits[] = {
|
} testInits[] = {
|
||||||
{"requires", T_REQUIRES},
|
{ "requires", T_REQUIRES },
|
||||||
{"greaterThan", T_GREATERTHAN},
|
{ "greaterThan", T_GREATERTHAN },
|
||||||
{"lessThan", T_LESSTHAN},
|
{ "lessThan", T_LESSTHAN },
|
||||||
{"equals", T_EQUALS},
|
{ "equals", T_EQUALS },
|
||||||
{"isEqual", T_EQUALS},
|
{ "isEqual", T_EQUALS },
|
||||||
{"versionAtLeast", T_VERSION_AT_LEAST},
|
{ "versionAtLeast", T_VERSION_AT_LEAST },
|
||||||
{"versionAtMost", T_VERSION_AT_MOST},
|
{ "versionAtMost", T_VERSION_AT_MOST },
|
||||||
{"exists", T_EXISTS},
|
{ "exists", T_EXISTS },
|
||||||
{"export", T_EXPORT},
|
{ "export", T_EXPORT },
|
||||||
{"clear", T_CLEAR},
|
{ "clear", T_CLEAR },
|
||||||
{"unset", T_UNSET},
|
{ "unset", T_UNSET },
|
||||||
{"eval", T_EVAL},
|
{ "eval", T_EVAL },
|
||||||
{"CONFIG", T_CONFIG},
|
{ "CONFIG", T_CONFIG },
|
||||||
{"if", T_IF},
|
{ "if", T_IF },
|
||||||
{"isActiveConfig", T_CONFIG},
|
{ "isActiveConfig", T_CONFIG },
|
||||||
{"system", T_SYSTEM},
|
{ "system", T_SYSTEM },
|
||||||
{"discard_from", T_DISCARD_FROM},
|
{ "discard_from", T_DISCARD_FROM },
|
||||||
{"defined", T_DEFINED},
|
{ "defined", T_DEFINED },
|
||||||
{"contains", T_CONTAINS},
|
{ "contains", T_CONTAINS },
|
||||||
{"infile", T_INFILE},
|
{ "infile", T_INFILE },
|
||||||
{"count", T_COUNT},
|
{ "count", T_COUNT },
|
||||||
{"isEmpty", T_ISEMPTY},
|
{ "isEmpty", T_ISEMPTY },
|
||||||
{"parseJson", T_PARSE_JSON},
|
{ "parseJson", T_PARSE_JSON },
|
||||||
{"load", T_LOAD},
|
{ "load", T_LOAD },
|
||||||
{"include", T_INCLUDE},
|
{ "include", T_INCLUDE },
|
||||||
{"debug", T_DEBUG},
|
{ "debug", T_DEBUG },
|
||||||
{"log", T_LOG},
|
{ "log", T_LOG },
|
||||||
{"message", T_MESSAGE},
|
{ "message", T_MESSAGE },
|
||||||
{"warning", T_WARNING},
|
{ "warning", T_WARNING },
|
||||||
{"error", T_ERROR},
|
{ "error", T_ERROR },
|
||||||
{"mkpath", T_MKPATH},
|
{ "mkpath", T_MKPATH },
|
||||||
{"write_file", T_WRITE_FILE},
|
{ "write_file", T_WRITE_FILE },
|
||||||
{"touch", T_TOUCH},
|
{ "touch", T_TOUCH },
|
||||||
{"cache", T_CACHE},
|
{ "cache", T_CACHE },
|
||||||
|
{ "reload_properties", T_RELOAD_PROPERTIES },
|
||||||
};
|
};
|
||||||
statics.functions.reserve((int)(sizeof(testInits)/sizeof(testInits[0])));
|
statics.functions.reserve((int)(sizeof(testInits)/sizeof(testInits[0])));
|
||||||
for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
|
for (unsigned i = 0; i < sizeof(testInits)/sizeof(testInits[0]); ++i)
|
||||||
@@ -251,23 +251,6 @@ QMakeEvaluator::getMemberArgs(const ProKey &func, int srclen, const ProStringLis
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(PROEVALUATOR_FULL)
|
|
||||||
static QString windowsErrorCode()
|
|
||||||
{
|
|
||||||
wchar_t *string = 0;
|
|
||||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
|
||||||
NULL,
|
|
||||||
GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPWSTR)&string,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
QString ret = QString::fromWCharArray(string);
|
|
||||||
LocalFree((HLOCAL)string);
|
|
||||||
return ret.trimmed();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QString
|
QString
|
||||||
QMakeEvaluator::quoteValue(const ProString &val)
|
QMakeEvaluator::quoteValue(const ProString &val)
|
||||||
{
|
{
|
||||||
@@ -392,14 +375,47 @@ static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ErrorPosition {
|
||||||
|
int line;
|
||||||
|
int column;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ErrorPosition calculateErrorPosition(const QByteArray &json, int offset)
|
||||||
|
{
|
||||||
|
ErrorPosition pos = { 0, 0 };
|
||||||
|
offset--; // offset is 1-based, switching to 0-based
|
||||||
|
for (int i = 0; i < offset; ++i) {
|
||||||
|
switch (json.at(i)) {
|
||||||
|
case '\n':
|
||||||
|
pos.line++;
|
||||||
|
pos.column = 0;
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
pos.column = (pos.column + 8) & ~7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pos.column++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Lines and columns in text editors are 1-based:
|
||||||
|
pos.line++;
|
||||||
|
pos.column++;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value)
|
QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value)
|
||||||
{
|
{
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
QJsonDocument document = QJsonDocument::fromJson(json, &error);
|
QJsonDocument document = QJsonDocument::fromJson(json, &error);
|
||||||
if (document.isNull()) {
|
if (document.isNull()) {
|
||||||
if (error.error != QJsonParseError::NoError)
|
if (error.error != QJsonParseError::NoError) {
|
||||||
evalError(fL1S("Error parsing json at offset %1: %2")
|
ErrorPosition errorPos = calculateErrorPosition(json, error.offset);
|
||||||
.arg(error.offset).arg(error.errorString()));
|
evalError(fL1S("Error parsing JSON at %1:%2: %3")
|
||||||
|
.arg(errorPos.line).arg(errorPos.column).arg(error.errorString()));
|
||||||
|
}
|
||||||
return QMakeEvaluator::ReturnFalse;
|
return QMakeEvaluator::ReturnFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,13 +436,16 @@ QMakeEvaluator::VisitReturn
|
|||||||
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
|
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
|
||||||
QMakeVfs::VfsFlags flags, const QString &contents)
|
QMakeVfs::VfsFlags flags, const QString &contents)
|
||||||
{
|
{
|
||||||
|
int oldId = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
|
||||||
|
int id = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsCreate);
|
||||||
QString errStr;
|
QString errStr;
|
||||||
if (!m_vfs->writeFile(fn, mode, flags, contents, &errStr)) {
|
if (!m_vfs->writeFile(id, mode, flags, contents, &errStr)) {
|
||||||
evalError(fL1S("Cannot write %1file %2: %3")
|
evalError(fL1S("Cannot write %1file %2: %3")
|
||||||
.arg(ctx, QDir::toNativeSeparators(fn), errStr));
|
.arg(ctx, QDir::toNativeSeparators(fn), errStr));
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
m_parser->discardFileFromCache(fn);
|
if (oldId)
|
||||||
|
m_parser->discardFileFromCache(oldId);
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,11 +541,9 @@ void QMakeEvaluator::populateDeps(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
|
||||||
int func_t, const ProKey &func, const ProStringList &args)
|
int func_t, const ProKey &func, const ProStringList &args, ProStringList &ret)
|
||||||
{
|
{
|
||||||
ProStringList ret;
|
|
||||||
|
|
||||||
traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args));
|
traceMsg("calling built-in $$%s(%s)", dbgKey(func), dbgSepStrList(args));
|
||||||
|
|
||||||
switch (func_t) {
|
switch (func_t) {
|
||||||
@@ -540,8 +557,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
int end = -1;
|
int end = -1;
|
||||||
if (func_t == E_SECTION) {
|
if (func_t == E_SECTION) {
|
||||||
if (args.count() != 3 && args.count() != 4) {
|
if (args.count() != 3 && args.count() != 4) {
|
||||||
evalError(fL1S("%1(var) section(var, sep, begin, end) requires"
|
evalError(fL1S("section(var, sep, begin, end) requires three or four arguments."));
|
||||||
" three or four arguments.").arg(func.toQString(m_tmp1)));
|
|
||||||
} else {
|
} else {
|
||||||
var = args[0];
|
var = args[0];
|
||||||
sep = args.at(1).toQString();
|
sep = args.at(1).toQString();
|
||||||
@@ -567,8 +583,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
if (regexp) {
|
if (regexp) {
|
||||||
QRegExp sepRx(sep);
|
QRegExp sepRx(sep);
|
||||||
for (const ProString &str : strings) {
|
for (const ProString &str : strings) {
|
||||||
const QString &rstr = str.toQString(m_tmp1).section(sepRx, beg, end);
|
const QString &rstr = str.toQString(m_tmp[m_toggle ^= 1]).section(sepRx, beg, end);
|
||||||
ret << (rstr.isSharedWith(m_tmp1) ? str : ProString(rstr).setSource(str));
|
ret << (rstr.isSharedWith(m_tmp[m_toggle]) ? str : ProString(rstr).setSource(str));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const ProString &str : strings) {
|
for (const ProString &str : strings) {
|
||||||
@@ -598,7 +614,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
int width = 0;
|
int width = 0;
|
||||||
bool zeropad = false;
|
bool zeropad = false;
|
||||||
bool leftalign = false;
|
bool leftalign = false;
|
||||||
enum {DefaultSign, PadSign, AlwaysSign } sign = DefaultSign;
|
enum { DefaultSign, PadSign, AlwaysSign } sign = DefaultSign;
|
||||||
if (args.count() >= 2) {
|
if (args.count() >= 2) {
|
||||||
const auto opts = split_value_list(args.at(1).toQStringRef());
|
const auto opts = split_value_list(args.at(1).toQStringRef());
|
||||||
for (const ProString &opt : opts) {
|
for (const ProString &opt : opts) {
|
||||||
@@ -696,9 +712,9 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
after = args[3];
|
after = args[3];
|
||||||
const ProStringList &var = values(map(args.at(0)));
|
const ProStringList &var = values(map(args.at(0)));
|
||||||
if (!var.isEmpty()) {
|
if (!var.isEmpty()) {
|
||||||
const ProFile *src = currentProFile();
|
int src = currentFileId();
|
||||||
for (const ProString &v : var)
|
for (const ProString &v : var)
|
||||||
if (const ProFile *s = v.sourceFile()) {
|
if (int s = v.sourceFile()) {
|
||||||
src = s;
|
src = s;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -714,9 +730,9 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep;
|
const QString &sep = (args.count() == 2) ? args.at(1).toQString(m_tmp1) : statics.field_sep;
|
||||||
const auto vars = values(map(args.at(0)));
|
const auto vars = values(map(args.at(0)));
|
||||||
for (const ProString &var : vars) {
|
for (const ProString &var : vars) {
|
||||||
const auto splits = var.toQString(m_tmp2).split(sep);
|
const auto splits = var.toQStringRef().split(sep);
|
||||||
for (const QString &splt : splits)
|
for (const auto &splt : splits)
|
||||||
ret << (splt.isSharedWith(m_tmp2) ? var : ProString(splt).setSource(var));
|
ret << ProString(splt).setSource(var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -802,7 +818,8 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
if (args.count() < 1 || args.count() > 2) {
|
if (args.count() < 1 || args.count() > 2) {
|
||||||
evalError(fL1S("cat(file, singleline=true) requires one or two arguments."));
|
evalError(fL1S("cat(file, singleline=true) requires one or two arguments."));
|
||||||
} else {
|
} else {
|
||||||
const QString &file = args.at(0).toQString(m_tmp1);
|
QString fn = resolvePath(m_option->expandEnvVars(args.at(0).toQString(m_tmp1)));
|
||||||
|
fn.detach();
|
||||||
|
|
||||||
bool blob = false;
|
bool blob = false;
|
||||||
bool lines = false;
|
bool lines = false;
|
||||||
@@ -817,7 +834,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
lines = true;
|
lines = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile qfile(resolvePath(m_option->expandEnvVars(file)));
|
QFile qfile(fn);
|
||||||
if (qfile.open(QIODevice::ReadOnly)) {
|
if (qfile.open(QIODevice::ReadOnly)) {
|
||||||
QTextStream stream(&qfile);
|
QTextStream stream(&qfile);
|
||||||
if (blob) {
|
if (blob) {
|
||||||
@@ -868,12 +885,10 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
evalError(fL1S("find(var, str) requires two arguments."));
|
evalError(fL1S("find(var, str) requires two arguments."));
|
||||||
} else {
|
} else {
|
||||||
QRegExp regx(args.at(1).toQString());
|
QRegExp regx(args.at(1).toQString());
|
||||||
int t = 0;
|
|
||||||
const auto vals = values(map(args.at(0)));
|
const auto vals = values(map(args.at(0)));
|
||||||
for (const ProString &val : vals) {
|
for (const ProString &val : vals) {
|
||||||
if (regx.indexIn(val.toQString(m_tmp[t])) != -1)
|
if (regx.indexIn(val.toQString(m_tmp[m_toggle ^= 1])) != -1)
|
||||||
ret += val;
|
ret += val;
|
||||||
t ^= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -895,7 +910,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
lines = true;
|
lines = true;
|
||||||
}
|
}
|
||||||
int exitCode;
|
int exitCode;
|
||||||
QByteArray bytes = getCommandOutput(args.at(0).toQString(m_tmp2), &exitCode);
|
QByteArray bytes = getCommandOutput(args.at(0).toQString(), &exitCode);
|
||||||
if (args.count() > 2 && !args.at(2).isEmpty()) {
|
if (args.count() > 2 && !args.at(2).isEmpty()) {
|
||||||
m_valuemapStack.top()[args.at(2).toKey()] =
|
m_valuemapStack.top()[args.at(2).toKey()] =
|
||||||
ProStringList(ProString(QString::number(exitCode)));
|
ProStringList(ProString(QString::number(exitCode)));
|
||||||
@@ -960,10 +975,10 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
struct {
|
struct {
|
||||||
char in, out;
|
char in, out;
|
||||||
} mapped_quotes[] = {
|
} mapped_quotes[] = {
|
||||||
{'n', '\n' },
|
{ 'n', '\n' },
|
||||||
{'t', '\t' },
|
{ 't', '\t' },
|
||||||
{'r', '\r' },
|
{ 'r', '\r' },
|
||||||
{0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
for (int i = 0; mapped_quotes[i].in; ++i) {
|
for (int i = 0; mapped_quotes[i].in; ++i) {
|
||||||
if (*(i_data+x+1) == QLatin1Char(mapped_quotes[i].in)) {
|
if (*(i_data+x+1) == QLatin1Char(mapped_quotes[i].in)) {
|
||||||
@@ -1049,27 +1064,38 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
dirs.append(fname + QLatin1Char('/'));
|
dirs.append(fname + QLatin1Char('/'));
|
||||||
}
|
}
|
||||||
if (regex.exactMatch(qdir[i]))
|
if (regex.exactMatch(qdir[i]))
|
||||||
ret += ProString(fname).setSource(currentProFile());
|
ret += ProString(fname).setSource(currentFileId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef PROEVALUATOR_FULL
|
#ifdef PROEVALUATOR_FULL
|
||||||
case E_PROMPT: {
|
case E_PROMPT: {
|
||||||
if (args.count() != 1) {
|
if (args.count() != 1 && args.count() != 2) {
|
||||||
evalError(fL1S("prompt(question) requires one argument."));
|
evalError(fL1S("prompt(question, [decorate=true]) requires one or two arguments."));
|
||||||
// } else if (currentFileName() == QLatin1String("-")) {
|
// } else if (currentFileName() == QLatin1String("-")) {
|
||||||
// evalError(fL1S("prompt(question) cannot be used when '-o -' is used"));
|
// evalError(fL1S("prompt(question) cannot be used when '-o -' is used"));
|
||||||
} else {
|
} else {
|
||||||
QString msg = m_option->expandEnvVars(args.at(0).toQString(m_tmp1));
|
QString msg = m_option->expandEnvVars(args.at(0).toQString(m_tmp1));
|
||||||
if (!msg.endsWith(QLatin1Char('?')))
|
bool decorate = true;
|
||||||
msg += QLatin1Char('?');
|
if (args.count() == 2)
|
||||||
fprintf(stderr, "Project PROMPT: %s ", qPrintable(msg));
|
decorate = isTrue(args.at(1));
|
||||||
|
if (decorate) {
|
||||||
|
if (!msg.endsWith(QLatin1Char('?')))
|
||||||
|
msg += QLatin1Char('?');
|
||||||
|
fprintf(stderr, "Project PROMPT: %s ", qPrintable(msg));
|
||||||
|
} else {
|
||||||
|
fputs(qPrintable(msg), stderr);
|
||||||
|
}
|
||||||
QFile qfile;
|
QFile qfile;
|
||||||
if (qfile.open(stdin, QIODevice::ReadOnly)) {
|
if (qfile.open(stdin, QIODevice::ReadOnly)) {
|
||||||
QTextStream t(&qfile);
|
QTextStream t(&qfile);
|
||||||
const QString &line = t.readLine();
|
const QString &line = t.readLine();
|
||||||
|
if (t.atEnd()) {
|
||||||
|
fputs("\n", stderr);
|
||||||
|
evalError(fL1S("Unexpected EOF."));
|
||||||
|
return ReturnError;
|
||||||
|
}
|
||||||
ret = split_value_list(QStringRef(&line));
|
ret = split_value_list(QStringRef(&line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1086,7 +1112,11 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
QString rstr = val.toQString(m_tmp1);
|
QString rstr = val.toQString(m_tmp1);
|
||||||
QString copy = rstr; // Force a detach on modify
|
QString copy = rstr; // Force a detach on modify
|
||||||
rstr.replace(before, after);
|
rstr.replace(before, after);
|
||||||
ret << (rstr.isSharedWith(m_tmp1) ? val : ProString(rstr).setSource(val));
|
ret << (rstr.isSharedWith(m_tmp1)
|
||||||
|
? val
|
||||||
|
: rstr.isSharedWith(m_tmp2)
|
||||||
|
? args.at(2)
|
||||||
|
: ProString(rstr).setSource(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1144,9 +1174,9 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
if (args.count() > 2) {
|
if (args.count() > 2) {
|
||||||
evalError(fL1S("absolute_path(path[, base]) requires one or two arguments."));
|
evalError(fL1S("absolute_path(path[, base]) requires one or two arguments."));
|
||||||
} else {
|
} else {
|
||||||
QString rstr = QDir::cleanPath(
|
QString arg = args.at(0).toQString(m_tmp1);
|
||||||
QDir(args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory())
|
QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
|
||||||
.absoluteFilePath(args.at(0).toQString(m_tmp1)));
|
QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
|
||||||
ret << (rstr.isSharedWith(m_tmp1)
|
ret << (rstr.isSharedWith(m_tmp1)
|
||||||
? args.at(0)
|
? args.at(0)
|
||||||
: args.count() > 1 && rstr.isSharedWith(m_tmp2)
|
: args.count() > 1 && rstr.isSharedWith(m_tmp2)
|
||||||
@@ -1158,9 +1188,10 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
if (args.count() > 2) {
|
if (args.count() > 2) {
|
||||||
evalError(fL1S("relative_path(path[, base]) requires one or two arguments."));
|
evalError(fL1S("relative_path(path[, base]) requires one or two arguments."));
|
||||||
} else {
|
} else {
|
||||||
QDir baseDir(args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory());
|
QString arg = args.at(0).toQString(m_tmp1);
|
||||||
QString rstr = baseDir.relativeFilePath(baseDir.absoluteFilePath(
|
QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory();
|
||||||
args.at(0).toQString(m_tmp1)));
|
QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg);
|
||||||
|
QString rstr = QDir(baseDir).relativeFilePath(absArg);
|
||||||
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
|
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1239,7 +1270,7 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||||
@@ -1305,7 +1336,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
|
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
|
||||||
ProFile *pro = m_parser->parsedProFile(fn, QMakeParser::ParseOnlyCached);
|
QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
|
||||||
|
int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly);
|
||||||
if (!pro)
|
if (!pro)
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
ProValueMap &vmap = m_valuemapStack.first();
|
ProValueMap &vmap = m_valuemapStack.first();
|
||||||
@@ -1324,7 +1356,22 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
}
|
}
|
||||||
++vit;
|
++vit;
|
||||||
}
|
}
|
||||||
pro->deref();
|
for (auto fit = m_functionDefs.testFunctions.begin(); fit != m_functionDefs.testFunctions.end(); ) {
|
||||||
|
if (fit->pro()->id() == pro)
|
||||||
|
fit = m_functionDefs.testFunctions.erase(fit);
|
||||||
|
else
|
||||||
|
++fit;
|
||||||
|
}
|
||||||
|
for (auto fit = m_functionDefs.replaceFunctions.begin(); fit != m_functionDefs.replaceFunctions.end(); ) {
|
||||||
|
if (fit->pro()->id() == pro)
|
||||||
|
fit = m_functionDefs.replaceFunctions.erase(fit);
|
||||||
|
else
|
||||||
|
++fit;
|
||||||
|
}
|
||||||
|
ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
|
||||||
|
int idx = iif.indexOf(ProString(fn));
|
||||||
|
if (idx >= 0)
|
||||||
|
iif.removeAt(idx);
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
case T_INFILE:
|
case T_INFILE:
|
||||||
@@ -1346,12 +1393,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
copy.detach();
|
copy.detach();
|
||||||
regx.setPattern(copy);
|
regx.setPattern(copy);
|
||||||
}
|
}
|
||||||
int t = 0;
|
|
||||||
const auto strings = vars.value(map(args.at(1)));
|
const auto strings = vars.value(map(args.at(1)));
|
||||||
for (const ProString &s : strings) {
|
for (const ProString &s : strings) {
|
||||||
if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[t]))) || s == qry)
|
if ((!regx.isEmpty() && regx.exactMatch(s.toQString(m_tmp[m_toggle ^= 1]))) || s == qry)
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
t ^= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
@@ -1365,7 +1410,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
VisitReturn ret = ReturnFalse;
|
VisitReturn ret = ReturnFalse;
|
||||||
QString contents = args.join(statics.field_sep);
|
QString contents = args.join(statics.field_sep);
|
||||||
ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
|
ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents),
|
||||||
m_current.pro->fileName(), m_current.line);
|
0, m_current.pro->fileName(), m_current.line);
|
||||||
if (m_cumulative || pro->isOk()) {
|
if (m_cumulative || pro->isOk()) {
|
||||||
m_locationStack.push(m_current);
|
m_locationStack.push(m_current);
|
||||||
visitProBlock(pro, pro->tokPtr());
|
visitProBlock(pro, pro->tokPtr());
|
||||||
@@ -1389,13 +1434,13 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
if (args.count() == 1)
|
if (args.count() == 1)
|
||||||
return returnBool(isActiveConfig(args.at(0).toQString(m_tmp2)));
|
return returnBool(isActiveConfig(args.at(0).toQStringRef()));
|
||||||
const QStringList &mutuals = args.at(1).toQString(m_tmp2).split(QLatin1Char('|'));
|
const auto mutuals = args.at(1).toQStringRef().split(QLatin1Char('|'));
|
||||||
const ProStringList &configs = values(statics.strCONFIG);
|
const ProStringList &configs = values(statics.strCONFIG);
|
||||||
|
|
||||||
for (int i = configs.size() - 1; i >= 0; i--) {
|
for (int i = configs.size() - 1; i >= 0; i--) {
|
||||||
for (int mut = 0; mut < mutuals.count(); mut++) {
|
for (int mut = 0; mut < mutuals.count(); mut++) {
|
||||||
if (configs[i] == mutuals[mut].trimmed())
|
if (configs[i].toQStringRef() == mutuals[mut].trimmed())
|
||||||
return returnBool(configs[i] == args[0]);
|
return returnBool(configs[i] == args[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1416,21 +1461,19 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
}
|
}
|
||||||
const ProStringList &l = values(map(args.at(0)));
|
const ProStringList &l = values(map(args.at(0)));
|
||||||
if (args.count() == 2) {
|
if (args.count() == 2) {
|
||||||
int t = 0;
|
|
||||||
for (int i = 0; i < l.size(); ++i) {
|
for (int i = 0; i < l.size(); ++i) {
|
||||||
const ProString &val = l[i];
|
const ProString &val = l[i];
|
||||||
if ((!regx.isEmpty() && regx.exactMatch(val.toQString(m_tmp[t]))) || val == qry)
|
if ((!regx.isEmpty() && regx.exactMatch(val.toQString(m_tmp[m_toggle ^= 1]))) || val == qry)
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
t ^= 1;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const QStringList &mutuals = args.at(2).toQString(m_tmp3).split(QLatin1Char('|'));
|
const auto mutuals = args.at(2).toQStringRef().split(QLatin1Char('|'));
|
||||||
for (int i = l.size() - 1; i >= 0; i--) {
|
for (int i = l.size() - 1; i >= 0; i--) {
|
||||||
const ProString val = l[i];
|
const ProString val = l[i];
|
||||||
for (int mut = 0; mut < mutuals.count(); mut++) {
|
for (int mut = 0; mut < mutuals.count(); mut++) {
|
||||||
if (val == mutuals[mut].trimmed()) {
|
if (val.toQStringRef() == mutuals[mut].trimmed()) {
|
||||||
return returnBool((!regx.isEmpty()
|
return returnBool((!regx.isEmpty()
|
||||||
&& regx.exactMatch(val.toQString(m_tmp2)))
|
&& regx.exactMatch(val.toQString(m_tmp[m_toggle ^= 1])))
|
||||||
|| val == qry);
|
|| val == qry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1495,7 +1538,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
return returnBool(values(map(args.at(0))).join(statics.field_sep)
|
return returnBool(values(map(args.at(0))).join(statics.field_sep)
|
||||||
== args.at(1).toQString(m_tmp1));
|
== args.at(1).toQStringRef());
|
||||||
case T_VERSION_AT_LEAST:
|
case T_VERSION_AT_LEAST:
|
||||||
case T_VERSION_AT_MOST: {
|
case T_VERSION_AT_MOST: {
|
||||||
if (args.count() != 2) {
|
if (args.count() != 2) {
|
||||||
@@ -1666,7 +1709,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
#ifndef QT_BOOTSTRAPPED
|
#ifndef QT_BOOTSTRAPPED
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.setProcessChannelMode(QProcess::ForwardedChannels);
|
proc.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
runProcess(&proc, args.at(0).toQString(m_tmp2));
|
runProcess(&proc, args.at(0).toQString());
|
||||||
return returnBool(proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0);
|
return returnBool(proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0);
|
||||||
#else
|
#else
|
||||||
int ec = system((QLatin1String("cd ")
|
int ec = system((QLatin1String("cd ")
|
||||||
@@ -1703,8 +1746,10 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
int slsh = file.lastIndexOf(QLatin1Char('/'));
|
int slsh = file.lastIndexOf(QLatin1Char('/'));
|
||||||
QString fn = file.mid(slsh+1);
|
QString fn = file.mid(slsh+1);
|
||||||
|
fn.detach();
|
||||||
if (fn.contains(QLatin1Char('*')) || fn.contains(QLatin1Char('?'))) {
|
if (fn.contains(QLatin1Char('*')) || fn.contains(QLatin1Char('?'))) {
|
||||||
QString dirstr = file.left(slsh+1);
|
QString dirstr = file.left(slsh+1);
|
||||||
|
dirstr.detach();
|
||||||
if (!QDir(dirstr).entryList(QStringList(fn)).isEmpty())
|
if (!QDir(dirstr).entryList(QStringList(fn)).isEmpty())
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
@@ -1717,7 +1762,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
#ifdef PROEVALUATOR_FULL
|
#ifdef PROEVALUATOR_FULL
|
||||||
const QString &fn = resolvePath(args.at(0).toQString(m_tmp1));
|
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
|
||||||
|
fn.detach();
|
||||||
if (!QDir::current().mkpath(fn)) {
|
if (!QDir::current().mkpath(fn)) {
|
||||||
evalError(fL1S("Cannot create directory %1.").arg(QDir::toNativeSeparators(fn)));
|
evalError(fL1S("Cannot create directory %1.").arg(QDir::toNativeSeparators(fn)));
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
@@ -1740,13 +1786,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
if (args.count() >= 3) {
|
if (args.count() >= 3) {
|
||||||
const auto opts = split_value_list(args.at(2).toQStringRef());
|
const auto opts = split_value_list(args.at(2).toQStringRef());
|
||||||
for (const ProString &opt : opts) {
|
for (const ProString &opt : opts) {
|
||||||
opt.toQString(m_tmp3);
|
if (opt == QLatin1String("append")) {
|
||||||
if (m_tmp3 == QLatin1String("append")) {
|
|
||||||
mode = QIODevice::Append;
|
mode = QIODevice::Append;
|
||||||
} else if (m_tmp3 == QLatin1String("exe")) {
|
} else if (opt == QLatin1String("exe")) {
|
||||||
flags |= QMakeVfs::VfsExecutable;
|
flags |= QMakeVfs::VfsExecutable;
|
||||||
} else {
|
} else {
|
||||||
evalError(fL1S("write_file(): invalid flag %1.").arg(m_tmp3));
|
evalError(fL1S("write_file(): invalid flag %1.").arg(opt.toQString(m_tmp3)));
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1764,40 +1809,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
#ifdef PROEVALUATOR_FULL
|
#ifdef PROEVALUATOR_FULL
|
||||||
const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1));
|
const QString &tfn = resolvePath(args.at(0).toQString(m_tmp1));
|
||||||
const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2));
|
const QString &rfn = resolvePath(args.at(1).toQString(m_tmp2));
|
||||||
#ifdef Q_OS_UNIX
|
QString error;
|
||||||
struct stat st;
|
if (!IoUtils::touchFile(tfn, rfn, &error)) {
|
||||||
if (stat(rfn.toLocal8Bit().constData(), &st)) {
|
evalError(error);
|
||||||
evalError(fL1S("Cannot stat() reference file %1: %2.").arg(rfn, fL1S(strerror(errno))));
|
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
struct utimbuf utb;
|
|
||||||
utb.actime = time(0);
|
|
||||||
utb.modtime = st.st_mtime;
|
|
||||||
if (utime(tfn.toLocal8Bit().constData(), &utb)) {
|
|
||||||
evalError(fL1S("Cannot touch %1: %2.").arg(tfn, fL1S(strerror(errno))));
|
|
||||||
return ReturnFalse;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
HANDLE rHand = CreateFile((wchar_t*)rfn.utf16(),
|
|
||||||
GENERIC_READ, FILE_SHARE_READ,
|
|
||||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (rHand == INVALID_HANDLE_VALUE) {
|
|
||||||
evalError(fL1S("Cannot open reference file %1: %2").arg(rfn, windowsErrorCode()));
|
|
||||||
return ReturnFalse;
|
|
||||||
}
|
|
||||||
FILETIME ft;
|
|
||||||
GetFileTime(rHand, 0, 0, &ft);
|
|
||||||
CloseHandle(rHand);
|
|
||||||
HANDLE wHand = CreateFile((wchar_t*)tfn.utf16(),
|
|
||||||
GENERIC_WRITE, FILE_SHARE_READ,
|
|
||||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (wHand == INVALID_HANDLE_VALUE) {
|
|
||||||
evalError(fL1S("Cannot open %1: %2").arg(tfn, windowsErrorCode()));
|
|
||||||
return ReturnFalse;
|
|
||||||
}
|
|
||||||
SetFileTime(wHand, 0, 0, &ft);
|
|
||||||
CloseHandle(wHand);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
@@ -1813,21 +1829,20 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
if (args.count() >= 2) {
|
if (args.count() >= 2) {
|
||||||
const auto opts = split_value_list(args.at(1).toQStringRef());
|
const auto opts = split_value_list(args.at(1).toQStringRef());
|
||||||
for (const ProString &opt : opts) {
|
for (const ProString &opt : opts) {
|
||||||
opt.toQString(m_tmp3);
|
if (opt == QLatin1String("transient")) {
|
||||||
if (m_tmp3 == QLatin1String("transient")) {
|
|
||||||
persist = false;
|
persist = false;
|
||||||
} else if (m_tmp3 == QLatin1String("super")) {
|
} else if (opt == QLatin1String("super")) {
|
||||||
target = TargetSuper;
|
target = TargetSuper;
|
||||||
} else if (m_tmp3 == QLatin1String("stash")) {
|
} else if (opt == QLatin1String("stash")) {
|
||||||
target = TargetStash;
|
target = TargetStash;
|
||||||
} else if (m_tmp3 == QLatin1String("set")) {
|
} else if (opt == QLatin1String("set")) {
|
||||||
mode = CacheSet;
|
mode = CacheSet;
|
||||||
} else if (m_tmp3 == QLatin1String("add")) {
|
} else if (opt == QLatin1String("add")) {
|
||||||
mode = CacheAdd;
|
mode = CacheAdd;
|
||||||
} else if (m_tmp3 == QLatin1String("sub")) {
|
} else if (opt == QLatin1String("sub")) {
|
||||||
mode = CacheSub;
|
mode = CacheSub;
|
||||||
} else {
|
} else {
|
||||||
evalError(fL1S("cache(): invalid flag %1.").arg(m_tmp3));
|
evalError(fL1S("cache(): invalid flag %1.").arg(opt.toQString(m_tmp3)));
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1969,6 +1984,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
|||||||
}
|
}
|
||||||
return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
|
return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr);
|
||||||
}
|
}
|
||||||
|
case T_RELOAD_PROPERTIES:
|
||||||
|
#ifdef QT_BUILD_QMAKE
|
||||||
|
m_option->reloadProperties();
|
||||||
|
#endif
|
||||||
|
return ReturnTrue;
|
||||||
default:
|
default:
|
||||||
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
|
evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
|
@@ -149,6 +149,7 @@ void QMakeEvaluator::initStatics()
|
|||||||
statics.strhost_build = QLatin1String("host_build");
|
statics.strhost_build = QLatin1String("host_build");
|
||||||
statics.strTEMPLATE = ProKey("TEMPLATE");
|
statics.strTEMPLATE = ProKey("TEMPLATE");
|
||||||
statics.strQMAKE_PLATFORM = ProKey("QMAKE_PLATFORM");
|
statics.strQMAKE_PLATFORM = ProKey("QMAKE_PLATFORM");
|
||||||
|
statics.strQMAKE_DIR_SEP = ProKey("QMAKE_DIR_SEP");
|
||||||
statics.strQMAKESPEC = ProKey("QMAKESPEC");
|
statics.strQMAKESPEC = ProKey("QMAKESPEC");
|
||||||
#ifdef PROEVALUATOR_FULL
|
#ifdef PROEVALUATOR_FULL
|
||||||
statics.strREQUIRES = ProKey("REQUIRES");
|
statics.strREQUIRES = ProKey("REQUIRES");
|
||||||
@@ -161,27 +162,27 @@ void QMakeEvaluator::initStatics()
|
|||||||
static const struct {
|
static const struct {
|
||||||
const char * const oldname, * const newname;
|
const char * const oldname, * const newname;
|
||||||
} mapInits[] = {
|
} mapInits[] = {
|
||||||
{"INTERFACES", "FORMS"},
|
{ "INTERFACES", "FORMS" },
|
||||||
{"QMAKE_POST_BUILD", "QMAKE_POST_LINK"},
|
{ "QMAKE_POST_BUILD", "QMAKE_POST_LINK" },
|
||||||
{"TARGETDEPS", "POST_TARGETDEPS"},
|
{ "TARGETDEPS", "POST_TARGETDEPS" },
|
||||||
{"LIBPATH", "QMAKE_LIBDIR"},
|
{ "LIBPATH", "QMAKE_LIBDIR" },
|
||||||
{"QMAKE_EXT_MOC", "QMAKE_EXT_CPP_MOC"},
|
{ "QMAKE_EXT_MOC", "QMAKE_EXT_CPP_MOC" },
|
||||||
{"QMAKE_MOD_MOC", "QMAKE_H_MOD_MOC"},
|
{ "QMAKE_MOD_MOC", "QMAKE_H_MOD_MOC" },
|
||||||
{"QMAKE_LFLAGS_SHAPP", "QMAKE_LFLAGS_APP"},
|
{ "QMAKE_LFLAGS_SHAPP", "QMAKE_LFLAGS_APP" },
|
||||||
{"PRECOMPH", "PRECOMPILED_HEADER"},
|
{ "PRECOMPH", "PRECOMPILED_HEADER" },
|
||||||
{"PRECOMPCPP", "PRECOMPILED_SOURCE"},
|
{ "PRECOMPCPP", "PRECOMPILED_SOURCE" },
|
||||||
{"INCPATH", "INCLUDEPATH"},
|
{ "INCPATH", "INCLUDEPATH" },
|
||||||
{"QMAKE_EXTRA_WIN_COMPILERS", "QMAKE_EXTRA_COMPILERS"},
|
{ "QMAKE_EXTRA_WIN_COMPILERS", "QMAKE_EXTRA_COMPILERS" },
|
||||||
{"QMAKE_EXTRA_UNIX_COMPILERS", "QMAKE_EXTRA_COMPILERS"},
|
{ "QMAKE_EXTRA_UNIX_COMPILERS", "QMAKE_EXTRA_COMPILERS" },
|
||||||
{"QMAKE_EXTRA_WIN_TARGETS", "QMAKE_EXTRA_TARGETS"},
|
{ "QMAKE_EXTRA_WIN_TARGETS", "QMAKE_EXTRA_TARGETS" },
|
||||||
{"QMAKE_EXTRA_UNIX_TARGETS", "QMAKE_EXTRA_TARGETS"},
|
{ "QMAKE_EXTRA_UNIX_TARGETS", "QMAKE_EXTRA_TARGETS" },
|
||||||
{"QMAKE_EXTRA_UNIX_INCLUDES", "QMAKE_EXTRA_INCLUDES"},
|
{ "QMAKE_EXTRA_UNIX_INCLUDES", "QMAKE_EXTRA_INCLUDES" },
|
||||||
{"QMAKE_EXTRA_UNIX_VARIABLES", "QMAKE_EXTRA_VARIABLES"},
|
{ "QMAKE_EXTRA_UNIX_VARIABLES", "QMAKE_EXTRA_VARIABLES" },
|
||||||
{"QMAKE_RPATH", "QMAKE_LFLAGS_RPATH"},
|
{ "QMAKE_RPATH", "QMAKE_LFLAGS_RPATH" },
|
||||||
{"QMAKE_FRAMEWORKDIR", "QMAKE_FRAMEWORKPATH"},
|
{ "QMAKE_FRAMEWORKDIR", "QMAKE_FRAMEWORKPATH" },
|
||||||
{"QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS"},
|
{ "QMAKE_FRAMEWORKDIR_FLAGS", "QMAKE_FRAMEWORKPATH_FLAGS" },
|
||||||
{"IN_PWD", "PWD"},
|
{ "IN_PWD", "PWD" },
|
||||||
{"DEPLOYMENT", "INSTALLS"}
|
{ "DEPLOYMENT", "INSTALLS" }
|
||||||
};
|
};
|
||||||
statics.varMap.reserve((int)(sizeof(mapInits)/sizeof(mapInits[0])));
|
statics.varMap.reserve((int)(sizeof(mapInits)/sizeof(mapInits[0])));
|
||||||
for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
|
for (unsigned i = 0; i < sizeof(mapInits)/sizeof(mapInits[0]); ++i)
|
||||||
@@ -222,6 +223,7 @@ QMakeEvaluator::QMakeEvaluator(QMakeGlobals *option, QMakeParser *parser, QMakeV
|
|||||||
m_skipLevel = 0;
|
m_skipLevel = 0;
|
||||||
#endif
|
#endif
|
||||||
m_listCount = 0;
|
m_listCount = 0;
|
||||||
|
m_toggle = 0;
|
||||||
m_valuemapStack.push(ProValueMap());
|
m_valuemapStack.push(ProValueMap());
|
||||||
m_valuemapInited = false;
|
m_valuemapInited = false;
|
||||||
}
|
}
|
||||||
@@ -267,13 +269,13 @@ void QMakeEvaluator::skipHashStr(const ushort *&tokPtr)
|
|||||||
|
|
||||||
// FIXME: this should not build new strings for direct sections.
|
// FIXME: this should not build new strings for direct sections.
|
||||||
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
|
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
|
||||||
ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, const ProFile *source)
|
ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, int source)
|
||||||
{
|
{
|
||||||
QString build;
|
QString build;
|
||||||
ProStringList ret;
|
ProStringList ret;
|
||||||
|
|
||||||
if (!source)
|
if (!source)
|
||||||
source = currentProFile();
|
source = currentFileId();
|
||||||
|
|
||||||
const QChar *vals_data = vals.data();
|
const QChar *vals_data = vals.data();
|
||||||
const int vals_len = vals.length();
|
const int vals_len = vals.length();
|
||||||
@@ -591,6 +593,24 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
|
|||||||
tokPtr += blockLen;
|
tokPtr += blockLen;
|
||||||
okey = true, or_op = false; // force next evaluation
|
okey = true, or_op = false; // force next evaluation
|
||||||
break;
|
break;
|
||||||
|
case TokBypassNesting:
|
||||||
|
blockLen = getBlockLen(tokPtr);
|
||||||
|
if ((m_cumulative || okey != or_op) && blockLen) {
|
||||||
|
ProValueMapStack savedValuemapStack = m_valuemapStack;
|
||||||
|
m_valuemapStack.clear();
|
||||||
|
m_valuemapStack.append(savedValuemapStack.takeFirst());
|
||||||
|
traceMsg("visiting nesting-bypassing block");
|
||||||
|
ret = visitProBlock(tokPtr);
|
||||||
|
traceMsg("visited nesting-bypassing block");
|
||||||
|
savedValuemapStack.prepend(m_valuemapStack.first());
|
||||||
|
m_valuemapStack = savedValuemapStack;
|
||||||
|
} else {
|
||||||
|
traceMsg("skipped nesting-bypassing block");
|
||||||
|
ret = ReturnTrue;
|
||||||
|
}
|
||||||
|
tokPtr += blockLen;
|
||||||
|
okey = true, or_op = false; // force next evaluation
|
||||||
|
break;
|
||||||
case TokTestDef:
|
case TokTestDef:
|
||||||
case TokReplaceDef:
|
case TokReplaceDef:
|
||||||
if (m_cumulative || okey != or_op) {
|
if (m_cumulative || okey != or_op) {
|
||||||
@@ -626,7 +646,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProBlock(
|
|||||||
evalError(fL1S("Conditional must expand to exactly one word."));
|
evalError(fL1S("Conditional must expand to exactly one word."));
|
||||||
okey = false;
|
okey = false;
|
||||||
} else {
|
} else {
|
||||||
okey = isActiveConfig(curr.at(0).toQString(m_tmp2), true);
|
okey = isActiveConfig(curr.at(0).toQStringRef(), true);
|
||||||
traceMsg("condition %s is %s", dbgStr(curr.at(0)), dbgBool(okey));
|
traceMsg("condition %s is %s", dbgStr(curr.at(0)), dbgBool(okey));
|
||||||
okey ^= invert;
|
okey ^= invert;
|
||||||
}
|
}
|
||||||
@@ -753,7 +773,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProLoop(
|
|||||||
}
|
}
|
||||||
infinite = true;
|
infinite = true;
|
||||||
} else {
|
} else {
|
||||||
const QString &itl = it_list.toQString(m_tmp1);
|
const QStringRef &itl = it_list.toQStringRef();
|
||||||
int dotdot = itl.indexOf(statics.strDotDot);
|
int dotdot = itl.indexOf(statics.strDotDot);
|
||||||
if (dotdot != -1) {
|
if (dotdot != -1) {
|
||||||
bool ok;
|
bool ok;
|
||||||
@@ -850,13 +870,13 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable(
|
|||||||
ProStringList varVal;
|
ProStringList varVal;
|
||||||
if (expandVariableReferences(tokPtr, sizeHint, &varVal, true) == ReturnError)
|
if (expandVariableReferences(tokPtr, sizeHint, &varVal, true) == ReturnError)
|
||||||
return ReturnError;
|
return ReturnError;
|
||||||
const QString &val = varVal.at(0).toQString(m_tmp1);
|
const QStringRef &val = varVal.at(0).toQStringRef();
|
||||||
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
|
if (val.length() < 4 || val.at(0) != QLatin1Char('s')) {
|
||||||
evalError(fL1S("The ~= operator can handle only the s/// function."));
|
evalError(fL1S("The ~= operator can handle only the s/// function."));
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
}
|
}
|
||||||
QChar sep = val.at(1);
|
QChar sep = val.at(1);
|
||||||
QStringList func = val.split(sep);
|
auto func = val.split(sep);
|
||||||
if (func.count() < 3 || func.count() > 4) {
|
if (func.count() < 3 || func.count() > 4) {
|
||||||
evalError(fL1S("The s/// function expects 3 or 4 arguments."));
|
evalError(fL1S("The s/// function expects 3 or 4 arguments."));
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
@@ -868,8 +888,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable(
|
|||||||
case_sense = func[3].indexOf(QLatin1Char('i')) == -1;
|
case_sense = func[3].indexOf(QLatin1Char('i')) == -1;
|
||||||
quote = func[3].indexOf(QLatin1Char('q')) != -1;
|
quote = func[3].indexOf(QLatin1Char('q')) != -1;
|
||||||
}
|
}
|
||||||
QString pattern = func[1];
|
QString pattern = func[1].toString();
|
||||||
QString replace = func[2];
|
QString replace = func[2].toString();
|
||||||
if (quote)
|
if (quote)
|
||||||
pattern = QRegExp::escape(pattern);
|
pattern = QRegExp::escape(pattern);
|
||||||
|
|
||||||
@@ -917,11 +937,14 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProVariable(
|
|||||||
setTemplate();
|
setTemplate();
|
||||||
else if (varName == statics.strQMAKE_PLATFORM)
|
else if (varName == statics.strQMAKE_PLATFORM)
|
||||||
m_featureRoots = 0;
|
m_featureRoots = 0;
|
||||||
|
else if (varName == statics.strQMAKE_DIR_SEP)
|
||||||
|
m_dirSep = first(varName);
|
||||||
else if (varName == statics.strQMAKESPEC) {
|
else if (varName == statics.strQMAKESPEC) {
|
||||||
if (!values(varName).isEmpty()) {
|
if (!values(varName).isEmpty()) {
|
||||||
QString spec = values(varName).first().toQString();
|
QString spec = values(varName).first().toQString();
|
||||||
if (IoUtils::isAbsolutePath(spec)) {
|
if (IoUtils::isAbsolutePath(spec)) {
|
||||||
m_qmakespec = spec;
|
m_qmakespec = spec;
|
||||||
|
m_qmakespecName = IoUtils::fileName(m_qmakespec).toString();
|
||||||
m_featureRoots = 0;
|
m_featureRoots = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -947,11 +970,9 @@ void QMakeEvaluator::setTemplate()
|
|||||||
values.erase(values.begin() + 1, values.end());
|
values.erase(values.begin() + 1, values.end());
|
||||||
}
|
}
|
||||||
if (!m_option->user_template_prefix.isEmpty()) {
|
if (!m_option->user_template_prefix.isEmpty()) {
|
||||||
QString val = values.first().toQString(m_tmp1);
|
ProString val = values.first();
|
||||||
if (!val.startsWith(m_option->user_template_prefix)) {
|
if (!val.startsWith(m_option->user_template_prefix))
|
||||||
val.prepend(m_option->user_template_prefix);
|
values = ProStringList(ProString(m_option->user_template_prefix + val));
|
||||||
values = ProStringList(ProString(val));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,6 +989,13 @@ static ProString msvcBinDirToQMakeArch(QString subdir)
|
|||||||
subdir = subdir.toLower();
|
subdir = subdir.toLower();
|
||||||
if (subdir == QLatin1String("amd64"))
|
if (subdir == QLatin1String("amd64"))
|
||||||
return ProString("x86_64");
|
return ProString("x86_64");
|
||||||
|
// Since 2017 the folder structure from here is HostX64|X86/x64|x86
|
||||||
|
idx = subdir.indexOf(QLatin1Char('\\'));
|
||||||
|
if (idx == -1)
|
||||||
|
return ProString("x86");
|
||||||
|
subdir.remove(0, idx + 1);
|
||||||
|
if (subdir == QLatin1String("x64"))
|
||||||
|
return ProString("x86_64");
|
||||||
return ProString(subdir);
|
return ProString(subdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,8 +1090,12 @@ void QMakeEvaluator::loadDefaults()
|
|||||||
vars[ProKey("QMAKE_HOST.arch")] << archStr;
|
vars[ProKey("QMAKE_HOST.arch")] << archStr;
|
||||||
|
|
||||||
# if defined(Q_CC_MSVC) // ### bogus condition, but nobody x-builds for msvc with a different qmake
|
# if defined(Q_CC_MSVC) // ### bogus condition, but nobody x-builds for msvc with a different qmake
|
||||||
|
// Since VS 2017 we need VCToolsInstallDir instead of VCINSTALLDIR
|
||||||
|
QString vcInstallDir = m_option->getEnv(QLatin1String("VCToolsInstallDir"));
|
||||||
|
if (vcInstallDir.isEmpty())
|
||||||
|
vcInstallDir = m_option->getEnv(QLatin1String("VCINSTALLDIR"));
|
||||||
vars[ProKey("QMAKE_TARGET.arch")] = msvcArchitecture(
|
vars[ProKey("QMAKE_TARGET.arch")] = msvcArchitecture(
|
||||||
m_option->getEnv(QLatin1String("VCINSTALLDIR")),
|
vcInstallDir,
|
||||||
m_option->getEnv(QLatin1String("PATH")));
|
m_option->getEnv(QLatin1String("PATH")));
|
||||||
# endif
|
# endif
|
||||||
#elif defined(Q_OS_UNIX)
|
#elif defined(Q_OS_UNIX)
|
||||||
@@ -1187,8 +1219,6 @@ bool QMakeEvaluator::loadSpecInternal()
|
|||||||
// This also ensures that m_featureRoots is valid.
|
// This also ensures that m_featureRoots is valid.
|
||||||
if (evaluateFeatureFile(QLatin1String("spec_post.prf")) != ReturnTrue)
|
if (evaluateFeatureFile(QLatin1String("spec_post.prf")) != ReturnTrue)
|
||||||
return false;
|
return false;
|
||||||
// The MinGW and x-build specs may change the separator; $$shell_{path,quote}() need it
|
|
||||||
m_dirSep = first(ProKey("QMAKE_DIR_SEP"));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1280,7 +1310,7 @@ void QMakeEvaluator::setupProject()
|
|||||||
{
|
{
|
||||||
setTemplate();
|
setTemplate();
|
||||||
ProValueMap &vars = m_valuemapStack.top();
|
ProValueMap &vars = m_valuemapStack.top();
|
||||||
ProFile *proFile = currentProFile();
|
int proFile = currentFileId();
|
||||||
vars[ProKey("TARGET")] << ProString(QFileInfo(currentFileName()).baseName()).setSource(proFile);
|
vars[ProKey("TARGET")] << ProString(QFileInfo(currentFileName()).baseName()).setSource(proFile);
|
||||||
vars[ProKey("_PRO_FILE_")] << ProString(currentFileName()).setSource(proFile);
|
vars[ProKey("_PRO_FILE_")] << ProString(currentFileName()).setSource(proFile);
|
||||||
vars[ProKey("_PRO_FILE_PWD_")] << ProString(currentDirectory()).setSource(proFile);
|
vars[ProKey("_PRO_FILE_PWD_")] << ProString(currentDirectory()).setSource(proFile);
|
||||||
@@ -1290,7 +1320,7 @@ void QMakeEvaluator::setupProject()
|
|||||||
void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
|
void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where)
|
||||||
{
|
{
|
||||||
if (!cmds.isEmpty()) {
|
if (!cmds.isEmpty()) {
|
||||||
ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1);
|
ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), 0, where, -1);
|
||||||
if (pro->isOk()) {
|
if (pro->isOk()) {
|
||||||
m_locationStack.push(m_current);
|
m_locationStack.push(m_current);
|
||||||
visitProBlock(pro, pro->tokPtr());
|
visitProBlock(pro, pro->tokPtr());
|
||||||
@@ -1411,6 +1441,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
|
|||||||
if (flags & LoadPreFiles) {
|
if (flags & LoadPreFiles) {
|
||||||
setupProject();
|
setupProject();
|
||||||
|
|
||||||
|
if (!m_option->extra_cmds[QMakeEvalEarly].isEmpty())
|
||||||
|
evaluateCommand(m_option->extra_cmds[QMakeEvalEarly], fL1S("(command line -early)"));
|
||||||
|
|
||||||
for (ProValueMap::ConstIterator it = m_extraVars.constBegin();
|
for (ProValueMap::ConstIterator it = m_extraVars.constBegin();
|
||||||
it != m_extraVars.constEnd(); ++it)
|
it != m_extraVars.constEnd(); ++it)
|
||||||
m_valuemapStack.first().insert(it.key(), it.value());
|
m_valuemapStack.first().insert(it.key(), it.value());
|
||||||
@@ -1422,8 +1455,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
|
|||||||
if ((vr = evaluateFeatureFile(QLatin1String("default_pre.prf"))) == ReturnError)
|
if ((vr = evaluateFeatureFile(QLatin1String("default_pre.prf"))) == ReturnError)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
if (!m_option->precmds.isEmpty()) {
|
if (!m_option->extra_cmds[QMakeEvalBefore].isEmpty()) {
|
||||||
evaluateCommand(m_option->precmds, fL1S("(command line)"));
|
evaluateCommand(m_option->extra_cmds[QMakeEvalBefore], fL1S("(command line)"));
|
||||||
|
|
||||||
// Again, after user configs, to override them
|
// Again, after user configs, to override them
|
||||||
applyExtraConfigs();
|
applyExtraConfigs();
|
||||||
@@ -1436,7 +1469,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
|
|||||||
debugMsg(1, "done visiting file %s", qPrintable(pro->fileName()));
|
debugMsg(1, "done visiting file %s", qPrintable(pro->fileName()));
|
||||||
|
|
||||||
if (flags & LoadPostFiles) {
|
if (flags & LoadPostFiles) {
|
||||||
evaluateCommand(m_option->postcmds, fL1S("(command line -after)"));
|
evaluateCommand(m_option->extra_cmds[QMakeEvalAfter], fL1S("(command line -after)"));
|
||||||
|
|
||||||
// Again, to ensure the project does not mess with us.
|
// Again, to ensure the project does not mess with us.
|
||||||
// Specifically, do not allow a project to override debug/release within a
|
// Specifically, do not allow a project to override debug/release within a
|
||||||
@@ -1446,6 +1479,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::visitProFile(
|
|||||||
if ((vr = evaluateFeatureFile(QLatin1String("default_post.prf"))) == ReturnError)
|
if ((vr = evaluateFeatureFile(QLatin1String("default_post.prf"))) == ReturnError)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
if (!m_option->extra_cmds[QMakeEvalLate].isEmpty())
|
||||||
|
evaluateCommand(m_option->extra_cmds[QMakeEvalLate], fL1S("(command line -late)"));
|
||||||
|
|
||||||
if ((vr = evaluateConfigFeatures()) == ReturnError)
|
if ((vr = evaluateConfigFeatures()) == ReturnError)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@@ -1493,7 +1529,7 @@ void QMakeEvaluator::updateFeaturePaths()
|
|||||||
feature_roots += m_option->getPathListEnv(QLatin1String("QMAKEFEATURES"));
|
feature_roots += m_option->getPathListEnv(QLatin1String("QMAKEFEATURES"));
|
||||||
feature_roots += m_qmakefeatures;
|
feature_roots += m_qmakefeatures;
|
||||||
feature_roots += m_option->splitPathList(
|
feature_roots += m_option->splitPathList(
|
||||||
m_option->propertyValue(ProKey("QMAKEFEATURES")).toQString(m_mtmp));
|
m_option->propertyValue(ProKey("QMAKEFEATURES")).toQString());
|
||||||
|
|
||||||
QStringList feature_bases;
|
QStringList feature_bases;
|
||||||
if (!m_buildRoot.isEmpty()) {
|
if (!m_buildRoot.isEmpty()) {
|
||||||
@@ -1568,6 +1604,14 @@ ProFile *QMakeEvaluator::currentProFile() const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int QMakeEvaluator::currentFileId() const
|
||||||
|
{
|
||||||
|
ProFile *pro = currentProFile();
|
||||||
|
if (pro)
|
||||||
|
return pro->id();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
QString QMakeEvaluator::currentFileName() const
|
QString QMakeEvaluator::currentFileName() const
|
||||||
{
|
{
|
||||||
ProFile *pro = currentProFile();
|
ProFile *pro = currentProFile();
|
||||||
@@ -1584,7 +1628,7 @@ QString QMakeEvaluator::currentDirectory() const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
|
bool QMakeEvaluator::isActiveConfig(const QStringRef &config, bool regex)
|
||||||
{
|
{
|
||||||
// magic types for easy flipping
|
// magic types for easy flipping
|
||||||
if (config == statics.strtrue)
|
if (config == statics.strtrue)
|
||||||
@@ -1596,21 +1640,17 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
|
|||||||
return m_hostBuild;
|
return m_hostBuild;
|
||||||
|
|
||||||
if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) {
|
if (regex && (config.contains(QLatin1Char('*')) || config.contains(QLatin1Char('?')))) {
|
||||||
QString cfg = config;
|
QRegExp re(config.toString(), Qt::CaseSensitive, QRegExp::Wildcard);
|
||||||
cfg.detach(); // Keep m_tmp out of QRegExp's cache
|
|
||||||
QRegExp re(cfg, Qt::CaseSensitive, QRegExp::Wildcard);
|
|
||||||
|
|
||||||
// mkspecs
|
// mkspecs
|
||||||
if (re.exactMatch(m_qmakespecName))
|
if (re.exactMatch(m_qmakespecName))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// CONFIG variable
|
// CONFIG variable
|
||||||
int t = 0;
|
|
||||||
const auto configValues = values(statics.strCONFIG);
|
const auto configValues = values(statics.strCONFIG);
|
||||||
for (const ProString &configValue : configValues) {
|
for (const ProString &configValue : configValues) {
|
||||||
if (re.exactMatch(configValue.toQString(m_tmp[t])))
|
if (re.exactMatch(configValue.toQString(m_tmp[m_toggle ^= 1])))
|
||||||
return true;
|
return true;
|
||||||
t ^= 1;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// mkspecs
|
// mkspecs
|
||||||
@@ -1618,7 +1658,7 @@ bool QMakeEvaluator::isActiveConfig(const QString &config, bool regex)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// CONFIG variable
|
// CONFIG variable
|
||||||
if (values(statics.strCONFIG).contains(ProString(config)))
|
if (values(statics.strCONFIG).contains(config))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1713,7 +1753,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBoolFunction(
|
|||||||
if (ret.at(0) == statics.strtrue)
|
if (ret.at(0) == statics.strtrue)
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
bool ok;
|
bool ok;
|
||||||
int val = ret.at(0).toQString(m_tmp1).toInt(&ok);
|
int val = ret.at(0).toInt(&ok);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
if (val)
|
if (val)
|
||||||
return ReturnTrue;
|
return ReturnTrue;
|
||||||
@@ -1762,8 +1802,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction(
|
|||||||
ProStringList args;
|
ProStringList args;
|
||||||
if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError)
|
if (expandVariableReferences(tokPtr, 5, &args, true) == ReturnError)
|
||||||
return ReturnError;
|
return ReturnError;
|
||||||
*ret = evaluateBuiltinExpand(func_t, func, args);
|
return evaluateBuiltinExpand(func_t, func, args, *ret);
|
||||||
return ReturnTrue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<ProKey, ProFunctionDef>::ConstIterator it =
|
QHash<ProKey, ProFunctionDef>::ConstIterator it =
|
||||||
@@ -1785,7 +1824,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional(
|
|||||||
const QStringRef &cond, const QString &where, int line)
|
const QStringRef &cond, const QString &where, int line)
|
||||||
{
|
{
|
||||||
VisitReturn ret = ReturnFalse;
|
VisitReturn ret = ReturnFalse;
|
||||||
ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar);
|
ProFile *pro = m_parser->parsedProBlock(cond, 0, where, line, QMakeParser::TestGrammar);
|
||||||
if (pro->isOk()) {
|
if (pro->isOk()) {
|
||||||
m_locationStack.push(m_current);
|
m_locationStack.push(m_current);
|
||||||
ret = visitProBlock(pro, pro->tokPtr());
|
ret = visitProBlock(pro, pro->tokPtr());
|
||||||
|
@@ -173,12 +173,13 @@ public:
|
|||||||
|
|
||||||
void setTemplate();
|
void setTemplate();
|
||||||
|
|
||||||
ProStringList split_value_list(const QStringRef &vals, const ProFile *source = 0);
|
ProStringList split_value_list(const QStringRef &vals, int source = 0);
|
||||||
VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
|
VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
|
||||||
|
|
||||||
QString currentFileName() const;
|
QString currentFileName() const;
|
||||||
QString currentDirectory() const;
|
QString currentDirectory() const;
|
||||||
ProFile *currentProFile() const;
|
ProFile *currentProFile() const;
|
||||||
|
int currentFileId() const;
|
||||||
QString resolvePath(const QString &fileName) const
|
QString resolvePath(const QString &fileName) const
|
||||||
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
|
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
|
||||||
|
|
||||||
@@ -209,7 +210,7 @@ public:
|
|||||||
VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret);
|
VisitReturn evaluateExpandFunction(const ProKey &function, const ushort *&tokPtr, ProStringList *ret);
|
||||||
VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
|
VisitReturn evaluateConditionalFunction(const ProKey &function, const ushort *&tokPtr);
|
||||||
|
|
||||||
ProStringList evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args);
|
VisitReturn evaluateBuiltinExpand(int func_t, const ProKey &function, const ProStringList &args, ProStringList &ret);
|
||||||
VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
|
VisitReturn evaluateBuiltinConditional(int func_t, const ProKey &function, const ProStringList &args);
|
||||||
|
|
||||||
VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1);
|
VisitReturn evaluateConditional(const QStringRef &cond, const QString &where, int line = -1);
|
||||||
@@ -220,7 +221,7 @@ public:
|
|||||||
void updateMkspecPaths();
|
void updateMkspecPaths();
|
||||||
void updateFeaturePaths();
|
void updateFeaturePaths();
|
||||||
|
|
||||||
bool isActiveConfig(const QString &config, bool regex = false);
|
bool isActiveConfig(const QStringRef &config, bool regex = false);
|
||||||
|
|
||||||
void populateDeps(
|
void populateDeps(
|
||||||
const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes,
|
const ProStringList &deps, const ProString &prefix, const ProStringList &suffixes,
|
||||||
@@ -282,6 +283,7 @@ public:
|
|||||||
QString m_outputDir;
|
QString m_outputDir;
|
||||||
|
|
||||||
int m_listCount;
|
int m_listCount;
|
||||||
|
int m_toggle;
|
||||||
bool m_valuemapInited;
|
bool m_valuemapInited;
|
||||||
bool m_hostBuild;
|
bool m_hostBuild;
|
||||||
QString m_qmakespec;
|
QString m_qmakespec;
|
||||||
@@ -301,7 +303,6 @@ public:
|
|||||||
ProStringList m_returnValue;
|
ProStringList m_returnValue;
|
||||||
ProValueMapStack m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii.
|
ProValueMapStack m_valuemapStack; // VariableName must be us-ascii, the content however can be non-us-ascii.
|
||||||
QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
|
QString m_tmp1, m_tmp2, m_tmp3, m_tmp[2]; // Temporaries for efficient toQString
|
||||||
mutable QString m_mtmp;
|
|
||||||
|
|
||||||
QMakeGlobals *m_option;
|
QMakeGlobals *m_option;
|
||||||
QMakeParser *m_parser;
|
QMakeParser *m_parser;
|
||||||
|
@@ -39,7 +39,7 @@
|
|||||||
r == ReturnNext ? "next" : \
|
r == ReturnNext ? "next" : \
|
||||||
r == ReturnReturn ? "return" : \
|
r == ReturnReturn ? "return" : \
|
||||||
"<invalid>")
|
"<invalid>")
|
||||||
# define dbgKey(s) qPrintable(s.toString().toQString())
|
# define dbgKey(s) s.toString().toQStringRef().toLocal8Bit().constData()
|
||||||
# define dbgStr(s) qPrintable(formatValue(s, true))
|
# define dbgStr(s) qPrintable(formatValue(s, true))
|
||||||
# define dbgStrList(s) qPrintable(formatValueList(s))
|
# define dbgStrList(s) qPrintable(formatValueList(s))
|
||||||
# define dbgSepStrList(s) qPrintable(formatValueList(s, true))
|
# define dbgSepStrList(s) qPrintable(formatValueList(s, true))
|
||||||
@@ -74,6 +74,7 @@ struct QMakeStatics {
|
|||||||
QString strhost_build;
|
QString strhost_build;
|
||||||
ProKey strTEMPLATE;
|
ProKey strTEMPLATE;
|
||||||
ProKey strQMAKE_PLATFORM;
|
ProKey strQMAKE_PLATFORM;
|
||||||
|
ProKey strQMAKE_DIR_SEP;
|
||||||
ProKey strQMAKESPEC;
|
ProKey strQMAKESPEC;
|
||||||
#ifdef PROEVALUATOR_FULL
|
#ifdef PROEVALUATOR_FULL
|
||||||
ProKey strREQUIRES;
|
ProKey strREQUIRES;
|
||||||
|
@@ -65,6 +65,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
using namespace QMakeInternal; // for IoUtils
|
||||||
|
|
||||||
#define fL1S(s) QString::fromLatin1(s)
|
#define fL1S(s) QString::fromLatin1(s)
|
||||||
|
|
||||||
@@ -93,9 +94,9 @@ QString QMakeGlobals::cleanSpec(QMakeCmdLineParserState &state, const QString &s
|
|||||||
{
|
{
|
||||||
QString ret = QDir::cleanPath(spec);
|
QString ret = QDir::cleanPath(spec);
|
||||||
if (ret.contains(QLatin1Char('/'))) {
|
if (ret.contains(QLatin1Char('/'))) {
|
||||||
QString absRet = QDir(state.pwd).absoluteFilePath(ret);
|
QString absRet = IoUtils::resolvePath(state.pwd, ret);
|
||||||
if (QFile::exists(absRet))
|
if (QFile::exists(absRet))
|
||||||
ret = QDir::cleanPath(absRet);
|
ret = absRet;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -108,10 +109,7 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
|
|||||||
QString arg = args.at(*pos);
|
QString arg = args.at(*pos);
|
||||||
switch (argState) {
|
switch (argState) {
|
||||||
case ArgConfig:
|
case ArgConfig:
|
||||||
if (state.after)
|
state.configs[state.phase] << arg;
|
||||||
state.postconfigs << arg;
|
|
||||||
else
|
|
||||||
state.preconfigs << arg;
|
|
||||||
break;
|
break;
|
||||||
case ArgSpec:
|
case ArgSpec:
|
||||||
qmakespec = args[*pos] = cleanSpec(state, arg);
|
qmakespec = args[*pos] = cleanSpec(state, arg);
|
||||||
@@ -126,20 +124,26 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
|
|||||||
user_template_prefix = arg;
|
user_template_prefix = arg;
|
||||||
break;
|
break;
|
||||||
case ArgCache:
|
case ArgCache:
|
||||||
cachefile = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg));
|
cachefile = args[*pos] = IoUtils::resolvePath(state.pwd, arg);
|
||||||
break;
|
break;
|
||||||
case ArgQtConf:
|
case ArgQtConf:
|
||||||
qtconf = args[*pos] = QDir::cleanPath(QDir(state.pwd).absoluteFilePath(arg));
|
qtconf = args[*pos] = IoUtils::resolvePath(state.pwd, arg);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (arg.startsWith(QLatin1Char('-'))) {
|
if (arg.startsWith(QLatin1Char('-'))) {
|
||||||
if (arg == QLatin1String("--")) {
|
if (arg == QLatin1String("--")) {
|
||||||
state.extraargs = args.mid(*pos + 1);
|
state.extraargs = args.mid(*pos + 1);
|
||||||
*pos = args.size();
|
args.erase(args.begin() + *pos, args.end());
|
||||||
return ArgumentsOk;
|
return ArgumentsOk;
|
||||||
}
|
}
|
||||||
if (arg == QLatin1String("-after"))
|
if (arg == QLatin1String("-early"))
|
||||||
state.after = true;
|
state.phase = QMakeEvalEarly;
|
||||||
|
else if (arg == QLatin1String("-before"))
|
||||||
|
state.phase = QMakeEvalBefore;
|
||||||
|
else if (arg == QLatin1String("-after"))
|
||||||
|
state.phase = QMakeEvalAfter;
|
||||||
|
else if (arg == QLatin1String("-late"))
|
||||||
|
state.phase = QMakeEvalLate;
|
||||||
else if (arg == QLatin1String("-config"))
|
else if (arg == QLatin1String("-config"))
|
||||||
argState = ArgConfig;
|
argState = ArgConfig;
|
||||||
else if (arg == QLatin1String("-nocache"))
|
else if (arg == QLatin1String("-nocache"))
|
||||||
@@ -163,10 +167,7 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
|
|||||||
else
|
else
|
||||||
return ArgumentUnknown;
|
return ArgumentUnknown;
|
||||||
} else if (arg.contains(QLatin1Char('='))) {
|
} else if (arg.contains(QLatin1Char('='))) {
|
||||||
if (state.after)
|
state.cmds[state.phase] << arg;
|
||||||
state.postcmds << arg;
|
|
||||||
else
|
|
||||||
state.precmds << arg;
|
|
||||||
} else {
|
} else {
|
||||||
return ArgumentUnknown;
|
return ArgumentUnknown;
|
||||||
}
|
}
|
||||||
@@ -181,18 +182,17 @@ QMakeGlobals::ArgumentReturn QMakeGlobals::addCommandLineArguments(
|
|||||||
|
|
||||||
void QMakeGlobals::commitCommandLineArguments(QMakeCmdLineParserState &state)
|
void QMakeGlobals::commitCommandLineArguments(QMakeCmdLineParserState &state)
|
||||||
{
|
{
|
||||||
if (!state.preconfigs.isEmpty())
|
|
||||||
state.precmds << (fL1S("CONFIG += ") + state.preconfigs.join(QLatin1Char(' ')));
|
|
||||||
if (!state.extraargs.isEmpty()) {
|
if (!state.extraargs.isEmpty()) {
|
||||||
QString extra = fL1S("QMAKE_EXTRA_ARGS =");
|
QString extra = fL1S("QMAKE_EXTRA_ARGS =");
|
||||||
foreach (const QString &ea, state.extraargs)
|
foreach (const QString &ea, state.extraargs)
|
||||||
extra += QLatin1Char(' ') + QMakeEvaluator::quoteValue(ProString(ea));
|
extra += QLatin1Char(' ') + QMakeEvaluator::quoteValue(ProString(ea));
|
||||||
state.precmds << extra;
|
state.cmds[QMakeEvalBefore] << extra;
|
||||||
|
}
|
||||||
|
for (int p = 0; p < 4; p++) {
|
||||||
|
if (!state.configs[p].isEmpty())
|
||||||
|
state.cmds[p] << (fL1S("CONFIG += ") + state.configs[p].join(QLatin1Char(' ')));
|
||||||
|
extra_cmds[p] = state.cmds[p].join(QLatin1Char('\n'));
|
||||||
}
|
}
|
||||||
precmds = state.precmds.join(QLatin1Char('\n'));
|
|
||||||
if (!state.postconfigs.isEmpty())
|
|
||||||
state.postcmds << (fL1S("CONFIG += ") + state.postconfigs.join(QLatin1Char(' ')));
|
|
||||||
postcmds = state.postcmds.join(QLatin1Char('\n'));
|
|
||||||
|
|
||||||
if (xqmakespec.isEmpty())
|
if (xqmakespec.isEmpty())
|
||||||
xqmakespec = qmakespec;
|
xqmakespec = qmakespec;
|
||||||
@@ -257,11 +257,11 @@ QStringList QMakeGlobals::splitPathList(const QString &val) const
|
|||||||
{
|
{
|
||||||
QStringList ret;
|
QStringList ret;
|
||||||
if (!val.isEmpty()) {
|
if (!val.isEmpty()) {
|
||||||
QDir bdir;
|
QString cwd(QDir::currentPath());
|
||||||
const QStringList vals = val.split(dirlist_sep);
|
const QStringList vals = val.split(dirlist_sep);
|
||||||
ret.reserve(vals.length());
|
ret.reserve(vals.length());
|
||||||
for (const QString &it : vals)
|
for (const QString &it : vals)
|
||||||
ret << QDir::cleanPath(bdir.absoluteFilePath(it));
|
ret << IoUtils::resolvePath(cwd, it);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -316,7 +316,7 @@ bool QMakeGlobals::initProperties()
|
|||||||
return false;
|
return false;
|
||||||
data = proc.readAll();
|
data = proc.readAll();
|
||||||
#else
|
#else
|
||||||
if (FILE *proc = QT_POPEN(QString(QMakeInternal::IoUtils::shellQuote(qmake_abslocation)
|
if (FILE *proc = QT_POPEN(QString(IoUtils::shellQuote(qmake_abslocation)
|
||||||
+ QLatin1String(" -query")).toLocal8Bit(), QT_POPEN_READ)) {
|
+ QLatin1String(" -query")).toLocal8Bit(), QT_POPEN_READ)) {
|
||||||
char buff[1024];
|
char buff[1024];
|
||||||
while (!feof(proc))
|
while (!feof(proc))
|
||||||
|
@@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class QMakeEvaluator;
|
class QMakeEvaluator;
|
||||||
|
|
||||||
|
enum QMakeEvalPhase { QMakeEvalEarly, QMakeEvalBefore, QMakeEvalAfter, QMakeEvalLate };
|
||||||
|
|
||||||
class QMakeBaseKey
|
class QMakeBaseKey
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -79,12 +81,13 @@ public:
|
|||||||
class QMAKE_EXPORT QMakeCmdLineParserState
|
class QMAKE_EXPORT QMakeCmdLineParserState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QMakeCmdLineParserState(const QString &_pwd) : pwd(_pwd), after(false) {}
|
QMakeCmdLineParserState(const QString &_pwd) : pwd(_pwd), phase(QMakeEvalBefore) {}
|
||||||
QString pwd;
|
QString pwd;
|
||||||
QStringList precmds, preconfigs, postcmds, postconfigs, extraargs;
|
QStringList cmds[4], configs[4];
|
||||||
bool after;
|
QStringList extraargs;
|
||||||
|
QMakeEvalPhase phase;
|
||||||
|
|
||||||
void flush() { after = false; }
|
void flush() { phase = QMakeEvalBefore; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMAKE_EXPORT QMakeGlobals
|
class QMAKE_EXPORT QMakeGlobals
|
||||||
@@ -101,12 +104,12 @@ public:
|
|||||||
QProcessEnvironment environment;
|
QProcessEnvironment environment;
|
||||||
#endif
|
#endif
|
||||||
QString qmake_abslocation;
|
QString qmake_abslocation;
|
||||||
QStringList qmake_args;
|
QStringList qmake_args, qmake_extra_args;
|
||||||
|
|
||||||
QString qtconf;
|
QString qtconf;
|
||||||
QString qmakespec, xqmakespec;
|
QString qmakespec, xqmakespec;
|
||||||
QString user_template, user_template_prefix;
|
QString user_template, user_template_prefix;
|
||||||
QString precmds, postcmds;
|
QString extra_cmds[4];
|
||||||
|
|
||||||
#ifdef PROEVALUATOR_DEBUG
|
#ifdef PROEVALUATOR_DEBUG
|
||||||
int debugLevel;
|
int debugLevel;
|
||||||
@@ -121,6 +124,7 @@ public:
|
|||||||
void setDirectories(const QString &input_dir, const QString &output_dir);
|
void setDirectories(const QString &input_dir, const QString &output_dir);
|
||||||
#ifdef QT_BUILD_QMAKE
|
#ifdef QT_BUILD_QMAKE
|
||||||
void setQMakeProperty(QMakeProperty *prop) { property = prop; }
|
void setQMakeProperty(QMakeProperty *prop) { property = prop; }
|
||||||
|
void reloadProperties() { property->reload(); }
|
||||||
ProString propertyValue(const ProKey &name) const { return property->value(name); }
|
ProString propertyValue(const ProKey &name) const { return property->value(name); }
|
||||||
#else
|
#else
|
||||||
static void parseProperties(const QByteArray &data, QHash<ProKey, ProString> &props);
|
static void parseProperties(const QByteArray &data, QHash<ProKey, ProString> &props);
|
||||||
|
@@ -49,12 +49,22 @@ ProFileCache::~ProFileCache()
|
|||||||
ent.pro->deref();
|
ent.pro->deref();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProFileCache::discardFile(const QString &fileName)
|
void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs)
|
||||||
|
{
|
||||||
|
int eid = vfs->idForFileName(fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly);
|
||||||
|
if (eid)
|
||||||
|
discardFile(eid);
|
||||||
|
int cid = vfs->idForFileName(fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly);
|
||||||
|
if (cid && cid != eid)
|
||||||
|
discardFile(cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProFileCache::discardFile(int id)
|
||||||
{
|
{
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
QMutexLocker lck(&mutex);
|
QMutexLocker lck(&mutex);
|
||||||
#endif
|
#endif
|
||||||
QHash<QString, Entry>::Iterator it = parsed_files.find(fileName);
|
auto it = parsed_files.find(id);
|
||||||
if (it != parsed_files.end()) {
|
if (it != parsed_files.end()) {
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
if (it->locker) {
|
if (it->locker) {
|
||||||
@@ -74,16 +84,16 @@ void ProFileCache::discardFile(const QString &fileName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProFileCache::discardFiles(const QString &prefix)
|
void ProFileCache::discardFiles(const QString &prefix, QMakeVfs *vfs)
|
||||||
{
|
{
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
QMutexLocker lck(&mutex);
|
QMutexLocker lck(&mutex);
|
||||||
#endif
|
#endif
|
||||||
QHash<QString, Entry>::Iterator
|
auto it = parsed_files.begin(), end = parsed_files.end();
|
||||||
it = parsed_files.begin(),
|
while (it != end) {
|
||||||
end = parsed_files.end();
|
// Note: this is empty for virtual files from other VFSes.
|
||||||
while (it != end)
|
QString fn = vfs->fileNameForId(it.key());
|
||||||
if (it.key().startsWith(prefix)) {
|
if (fn.startsWith(prefix)) {
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
if (it->locker) {
|
if (it->locker) {
|
||||||
if (!it->locker->done) {
|
if (!it->locker->done) {
|
||||||
@@ -102,6 +112,7 @@ void ProFileCache::discardFiles(const QString &prefix)
|
|||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////// Parser ///////////
|
////////// Parser ///////////
|
||||||
@@ -115,6 +126,7 @@ static struct {
|
|||||||
QString strfor;
|
QString strfor;
|
||||||
QString strdefineTest;
|
QString strdefineTest;
|
||||||
QString strdefineReplace;
|
QString strdefineReplace;
|
||||||
|
QString strbypassNesting;
|
||||||
QString stroption;
|
QString stroption;
|
||||||
QString strreturn;
|
QString strreturn;
|
||||||
QString strnext;
|
QString strnext;
|
||||||
@@ -138,6 +150,7 @@ void QMakeParser::initialize()
|
|||||||
statics.strfor = QLatin1String("for");
|
statics.strfor = QLatin1String("for");
|
||||||
statics.strdefineTest = QLatin1String("defineTest");
|
statics.strdefineTest = QLatin1String("defineTest");
|
||||||
statics.strdefineReplace = QLatin1String("defineReplace");
|
statics.strdefineReplace = QLatin1String("defineReplace");
|
||||||
|
statics.strbypassNesting = QLatin1String("bypassNesting");
|
||||||
statics.stroption = QLatin1String("option");
|
statics.stroption = QLatin1String("option");
|
||||||
statics.strreturn = QLatin1String("return");
|
statics.strreturn = QLatin1String("return");
|
||||||
statics.strnext = QLatin1String("next");
|
statics.strnext = QLatin1String("next");
|
||||||
@@ -162,18 +175,15 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler
|
|||||||
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||||
{
|
{
|
||||||
ProFile *pro;
|
ProFile *pro;
|
||||||
if ((flags & (ParseUseCache|ParseOnlyCached)) && m_cache) {
|
QMakeVfs::VfsFlags vfsFlags = ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative
|
||||||
|
: QMakeVfs::VfsExact);
|
||||||
|
int id = m_vfs->idForFileName(fileName, vfsFlags);
|
||||||
|
if ((flags & ParseUseCache) && m_cache) {
|
||||||
ProFileCache::Entry *ent;
|
ProFileCache::Entry *ent;
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_cache->mutex);
|
QMutexLocker locker(&m_cache->mutex);
|
||||||
#endif
|
#endif
|
||||||
QHash<QString, ProFileCache::Entry>::Iterator it;
|
auto it = m_cache->parsed_files.find(id);
|
||||||
#ifdef PROEVALUATOR_DUAL_VFS
|
|
||||||
QString virtFileName = ((flags & ParseCumulative) ? '-' : '+') + fileName;
|
|
||||||
it = m_cache->parsed_files.find(virtFileName);
|
|
||||||
if (it == m_cache->parsed_files.end())
|
|
||||||
#endif
|
|
||||||
it = m_cache->parsed_files.find(fileName);
|
|
||||||
if (it != m_cache->parsed_files.end()) {
|
if (it != m_cache->parsed_files.end()) {
|
||||||
ent = &*it;
|
ent = &*it;
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
@@ -190,24 +200,15 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
|||||||
#endif
|
#endif
|
||||||
if ((pro = ent->pro))
|
if ((pro = ent->pro))
|
||||||
pro->ref();
|
pro->ref();
|
||||||
} else if (!(flags & ParseOnlyCached)) {
|
} else {
|
||||||
QString contents;
|
ent = &m_cache->parsed_files[id];
|
||||||
QMakeVfs::VfsFlags vfsFlags =
|
|
||||||
((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
|
|
||||||
bool virt = false;
|
|
||||||
#ifdef PROEVALUATOR_DUAL_VFS
|
|
||||||
virt = m_vfs->readVirtualFile(fileName, vfsFlags, &contents);
|
|
||||||
if (virt)
|
|
||||||
ent = &m_cache->parsed_files[virtFileName];
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
ent = &m_cache->parsed_files[fileName];
|
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
ent->locker = new ProFileCache::Entry::Locker;
|
ent->locker = new ProFileCache::Entry::Locker;
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
#endif
|
#endif
|
||||||
if (virt || readFile(fileName, vfsFlags | QMakeVfs::VfsNoVirtual, flags, &contents)) {
|
QString contents;
|
||||||
pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
|
if (readFile(id, flags, &contents)) {
|
||||||
|
pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
|
||||||
pro->itemsRef()->squeeze();
|
pro->itemsRef()->squeeze();
|
||||||
pro->ref();
|
pro->ref();
|
||||||
} else {
|
} else {
|
||||||
@@ -224,46 +225,39 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
|||||||
ent->locker = 0;
|
ent->locker = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
|
||||||
pro = 0;
|
|
||||||
}
|
}
|
||||||
} else if (!(flags & ParseOnlyCached)) {
|
} else {
|
||||||
QString contents;
|
QString contents;
|
||||||
QMakeVfs::VfsFlags vfsFlags =
|
if (readFile(id, flags, &contents))
|
||||||
((flags & ParseCumulative) ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact);
|
pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar);
|
||||||
if (readFile(fileName, vfsFlags, flags, &contents))
|
|
||||||
pro = parsedProBlock(QStringRef(&contents), fileName, 1, FullGrammar);
|
|
||||||
else
|
else
|
||||||
pro = 0;
|
pro = 0;
|
||||||
} else {
|
|
||||||
pro = 0;
|
|
||||||
}
|
}
|
||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFile *QMakeParser::parsedProBlock(
|
ProFile *QMakeParser::parsedProBlock(
|
||||||
const QStringRef &contents, const QString &name, int line, SubGrammar grammar)
|
const QStringRef &contents, int id, const QString &name, int line, SubGrammar grammar)
|
||||||
{
|
{
|
||||||
ProFile *pro = new ProFile(name);
|
ProFile *pro = new ProFile(id, name);
|
||||||
read(pro, contents, line, grammar);
|
read(pro, contents, line, grammar);
|
||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMakeParser::discardFileFromCache(const QString &fileName)
|
void QMakeParser::discardFileFromCache(int id)
|
||||||
{
|
{
|
||||||
if (m_cache)
|
if (m_cache)
|
||||||
m_cache->discardFile(fileName);
|
m_cache->discardFile(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMakeParser::readFile(
|
bool QMakeParser::readFile(int id, ParseFlags flags, QString *contents)
|
||||||
const QString &fn, QMakeVfs::VfsFlags vfsFlags, ParseFlags flags, QString *contents)
|
|
||||||
{
|
{
|
||||||
QString errStr;
|
QString errStr;
|
||||||
QMakeVfs::ReadResult result = m_vfs->readFile(fn, vfsFlags, contents, &errStr);
|
QMakeVfs::ReadResult result = m_vfs->readFile(id, contents, &errStr);
|
||||||
if (result != QMakeVfs::ReadOk) {
|
if (result != QMakeVfs::ReadOk) {
|
||||||
if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound))
|
if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound))
|
||||||
m_handler->message(QMakeParserHandler::ParserIoError,
|
m_handler->message(QMakeParserHandler::ParserIoError,
|
||||||
fL1S("Cannot read %1: %2").arg(fn, errStr));
|
fL1S("Cannot read %1: %2").arg(m_vfs->fileNameForId(id), errStr));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -1171,6 +1165,25 @@ void QMakeParser::finalizeCall(ushort *&tokPtr, ushort *uc, ushort *ptr, int arg
|
|||||||
}
|
}
|
||||||
parseError(fL1S("%1(function) requires one literal argument.").arg(*defName));
|
parseError(fL1S("%1(function) requires one literal argument.").arg(*defName));
|
||||||
return;
|
return;
|
||||||
|
} else if (m_tmp == statics.strbypassNesting) {
|
||||||
|
if (*uce != TokFuncTerminator) {
|
||||||
|
bogusTest(tokPtr, fL1S("%1() requires zero arguments.").arg(m_tmp));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(m_blockstack.top().nest & NestFunction)) {
|
||||||
|
bogusTest(tokPtr, fL1S("Unexpected %1().").arg(m_tmp));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_invert) {
|
||||||
|
bogusTest(tokPtr, fL1S("Unexpected NOT operator in front of %1().").arg(m_tmp));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushScopes(tokPtr);
|
||||||
|
putLineMarker(tokPtr);
|
||||||
|
putOperator(tokPtr);
|
||||||
|
putTok(tokPtr, TokBypassNesting);
|
||||||
|
enterScope(tokPtr, true, StCtrl);
|
||||||
|
return;
|
||||||
} else if (m_tmp == statics.strreturn) {
|
} else if (m_tmp == statics.strreturn) {
|
||||||
if (m_blockstack.top().nest & NestFunction) {
|
if (m_blockstack.top().nest & NestFunction) {
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
@@ -1439,7 +1452,7 @@ static bool getBlock(const ushort *tokens, int limit, int &offset, QString *outS
|
|||||||
"TokReturn", "TokBreak", "TokNext",
|
"TokReturn", "TokBreak", "TokNext",
|
||||||
"TokNot", "TokAnd", "TokOr",
|
"TokNot", "TokAnd", "TokOr",
|
||||||
"TokBranch", "TokForLoop",
|
"TokBranch", "TokForLoop",
|
||||||
"TokTestDef", "TokReplaceDef"
|
"TokTestDef", "TokReplaceDef", "TokBypassNesting"
|
||||||
};
|
};
|
||||||
|
|
||||||
while (offset != limit) {
|
while (offset != limit) {
|
||||||
@@ -1523,6 +1536,9 @@ static bool getBlock(const ushort *tokens, int limit, int &offset, QString *outS
|
|||||||
if (ok)
|
if (ok)
|
||||||
ok = getSubBlock(tokens, limit, offset, outStr, indent, "body");
|
ok = getSubBlock(tokens, limit, offset, outStr, indent, "body");
|
||||||
break;
|
break;
|
||||||
|
case TokBypassNesting:
|
||||||
|
ok = getSubBlock(tokens, limit, offset, outStr, indent, "block");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(!"unhandled token");
|
Q_ASSERT(!"unhandled token");
|
||||||
}
|
}
|
||||||
|
@@ -75,7 +75,6 @@ public:
|
|||||||
enum ParseFlag {
|
enum ParseFlag {
|
||||||
ParseDefault = 0,
|
ParseDefault = 0,
|
||||||
ParseUseCache = 1,
|
ParseUseCache = 1,
|
||||||
ParseOnlyCached = 2,
|
|
||||||
ParseReportMissing = 4,
|
ParseReportMissing = 4,
|
||||||
#ifdef PROEVALUATOR_DUAL_VFS
|
#ifdef PROEVALUATOR_DUAL_VFS
|
||||||
ParseCumulative = 8
|
ParseCumulative = 8
|
||||||
@@ -90,10 +89,10 @@ public:
|
|||||||
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
|
enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar };
|
||||||
// fileName is expected to be absolute and cleanPath()ed.
|
// fileName is expected to be absolute and cleanPath()ed.
|
||||||
ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault);
|
ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault);
|
||||||
ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0,
|
ProFile *parsedProBlock(const QStringRef &contents, int id, const QString &name, int line = 0,
|
||||||
SubGrammar grammar = FullGrammar);
|
SubGrammar grammar = FullGrammar);
|
||||||
|
|
||||||
void discardFileFromCache(const QString &fileName);
|
void discardFileFromCache(int id);
|
||||||
|
|
||||||
#ifdef PROPARSER_DEBUG
|
#ifdef PROPARSER_DEBUG
|
||||||
static QString formatProBlock(const QString &block);
|
static QString formatProBlock(const QString &block);
|
||||||
@@ -132,7 +131,7 @@ private:
|
|||||||
ushort terminator; // '}' if replace function call is braced, ':' if test function
|
ushort terminator; // '}' if replace function call is braced, ':' if test function
|
||||||
};
|
};
|
||||||
|
|
||||||
bool readFile(const QString &fn, QMakeVfs::VfsFlags vfsFlags, QMakeParser::ParseFlags flags, QString *contents);
|
bool readFile(int id, QMakeParser::ParseFlags flags, QString *contents);
|
||||||
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
|
void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar);
|
||||||
|
|
||||||
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
|
ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok);
|
||||||
@@ -201,8 +200,9 @@ public:
|
|||||||
ProFileCache() {}
|
ProFileCache() {}
|
||||||
~ProFileCache();
|
~ProFileCache();
|
||||||
|
|
||||||
void discardFile(const QString &fileName);
|
void discardFile(int id);
|
||||||
void discardFiles(const QString &prefix);
|
void discardFile(const QString &fileName, QMakeVfs *vfs);
|
||||||
|
void discardFiles(const QString &prefix, QMakeVfs *vfs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Entry {
|
struct Entry {
|
||||||
@@ -218,7 +218,7 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
QHash<QString, Entry> parsed_files;
|
QHash<int, Entry> parsed_files;
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -51,19 +51,85 @@ QMakeVfs::QMakeVfs()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags,
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
|
QMutex QMakeVfs::s_mutex;
|
||||||
|
#endif
|
||||||
|
QAtomicInt QMakeVfs::s_fileIdCounter;
|
||||||
|
QHash<QString, int> QMakeVfs::s_fileIdMap;
|
||||||
|
QHash<int, QString> QMakeVfs::s_idFileMap;
|
||||||
|
|
||||||
|
int QMakeVfs::idForFileName(const QString &fn, VfsFlags flags)
|
||||||
|
{
|
||||||
|
#ifdef PROEVALUATOR_DUAL_VFS
|
||||||
|
{
|
||||||
|
# ifdef PROPARSER_THREAD_SAFE
|
||||||
|
QMutexLocker locker(&m_vmutex);
|
||||||
|
# endif
|
||||||
|
int idx = (flags & VfsCumulative) ? 1 : 0;
|
||||||
|
if (flags & VfsCreate) {
|
||||||
|
int &id = m_virtualFileIdMap[idx][fn];
|
||||||
|
if (!id) {
|
||||||
|
id = ++s_fileIdCounter;
|
||||||
|
m_virtualIdFileMap[id] = fn;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
int id = m_virtualFileIdMap[idx].value(fn);
|
||||||
|
if (id || (flags & VfsCreatedOnly))
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!(flags & VfsAccessedOnly)) {
|
||||||
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
#endif
|
||||||
|
int &id = s_fileIdMap[fn];
|
||||||
|
if (!id) {
|
||||||
|
id = ++s_fileIdCounter;
|
||||||
|
s_idFileMap[id] = fn;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
return s_fileIdMap.value(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QMakeVfs::fileNameForId(int id)
|
||||||
|
{
|
||||||
|
#ifdef PROEVALUATOR_DUAL_VFS
|
||||||
|
{
|
||||||
|
# ifdef PROPARSER_THREAD_SAFE
|
||||||
|
QMutexLocker locker(&m_vmutex);
|
||||||
|
# endif
|
||||||
|
const QString &fn = m_virtualIdFileMap.value(id);
|
||||||
|
if (!fn.isEmpty())
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
#endif
|
||||||
|
return s_idFileMap.value(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMakeVfs::clearIds()
|
||||||
|
{
|
||||||
|
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
|
QMutexLocker locker(&s_mutex);
|
||||||
|
#endif
|
||||||
|
s_fileIdCounter = 0;
|
||||||
|
s_fileIdMap.clear();
|
||||||
|
s_idFileMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags,
|
||||||
const QString &contents, QString *errStr)
|
const QString &contents, QString *errStr)
|
||||||
{
|
{
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
# ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
# endif
|
# endif
|
||||||
#ifdef PROEVALUATOR_DUAL_VFS
|
QString *cont = &m_files[id];
|
||||||
QString *cont = &m_files[((flags & VfsCumulative) ? '-' : '+') + fn];
|
|
||||||
#else
|
|
||||||
QString *cont = &m_files[fn];
|
|
||||||
Q_UNUSED(flags)
|
Q_UNUSED(flags)
|
||||||
#endif
|
|
||||||
if (mode & QIODevice::Append)
|
if (mode & QIODevice::Append)
|
||||||
*cont += contents;
|
*cont += contents;
|
||||||
else
|
else
|
||||||
@@ -71,13 +137,13 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags f
|
|||||||
Q_UNUSED(errStr)
|
Q_UNUSED(errStr)
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
QFileInfo qfi(fn);
|
QFileInfo qfi(fileNameForId(id));
|
||||||
if (!QDir::current().mkpath(qfi.path())) {
|
if (!QDir::current().mkpath(qfi.path())) {
|
||||||
*errStr = fL1S("Cannot create parent directory");
|
*errStr = fL1S("Cannot create parent directory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QByteArray bytes = contents.toLocal8Bit();
|
QByteArray bytes = contents.toLocal8Bit();
|
||||||
QFile cfile(fn);
|
QFile cfile(qfi.filePath());
|
||||||
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
if (cfile.readAll() == bytes) {
|
if (cfile.readAll() == bytes) {
|
||||||
if (flags & VfsExecutable) {
|
if (flags & VfsExecutable) {
|
||||||
@@ -108,53 +174,13 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags f
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PROEVALUATOR_FULL
|
QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errStr)
|
||||||
bool QMakeVfs::readVirtualFile(const QString &fn, VfsFlags flags, QString *contents)
|
|
||||||
{
|
|
||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
|
||||||
QMutexLocker locker(&m_mutex);
|
|
||||||
# endif
|
|
||||||
QHash<QString, QString>::ConstIterator it;
|
|
||||||
# ifdef PROEVALUATOR_DUAL_VFS
|
|
||||||
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
|
|
||||||
if (it != m_files.constEnd()) {
|
|
||||||
*contents = *it;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
it = m_files.constFind(fn);
|
|
||||||
if (it != m_files.constEnd()
|
|
||||||
&& it->constData() != m_magicMissing.constData()
|
|
||||||
&& it->constData() != m_magicExisting.constData()) {
|
|
||||||
*contents = *it;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Q_UNUSED(flags)
|
|
||||||
# endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QMakeVfs::ReadResult QMakeVfs::readFile(
|
|
||||||
const QString &fn, VfsFlags flags, QString *contents, QString *errStr)
|
|
||||||
{
|
{
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
# ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
# endif
|
# endif
|
||||||
QHash<QString, QString>::ConstIterator it;
|
auto it = m_files.constFind(id);
|
||||||
# ifdef PROEVALUATOR_DUAL_VFS
|
|
||||||
if (!(flags & VfsNoVirtual)) {
|
|
||||||
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
|
|
||||||
if (it != m_files.constEnd()) {
|
|
||||||
*contents = *it;
|
|
||||||
return ReadOk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
Q_UNUSED(flags)
|
|
||||||
# endif
|
|
||||||
it = m_files.constFind(fn);
|
|
||||||
if (it != m_files.constEnd()) {
|
if (it != m_files.constEnd()) {
|
||||||
if (it->constData() == m_magicMissing.constData()) {
|
if (it->constData() == m_magicMissing.constData()) {
|
||||||
*errStr = fL1S("No such file or directory");
|
*errStr = fL1S("No such file or directory");
|
||||||
@@ -165,15 +191,13 @@ QMakeVfs::ReadResult QMakeVfs::readFile(
|
|||||||
return ReadOk;
|
return ReadOk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
Q_UNUSED(flags)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QFile file(fn);
|
QFile file(fileNameForId(id));
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
m_files[fn] = m_magicMissing;
|
m_files[id] = m_magicMissing;
|
||||||
#endif
|
#endif
|
||||||
*errStr = fL1S("No such file or directory");
|
*errStr = fL1S("No such file or directory");
|
||||||
return ReadNotFound;
|
return ReadNotFound;
|
||||||
@@ -182,7 +206,7 @@ QMakeVfs::ReadResult QMakeVfs::readFile(
|
|||||||
return ReadOtherError;
|
return ReadOtherError;
|
||||||
}
|
}
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
m_files[fn] = m_magicExisting;
|
m_files[id] = m_magicExisting;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QByteArray bcont = file.readAll();
|
QByteArray bcont = file.readAll();
|
||||||
@@ -205,15 +229,8 @@ bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
|
|||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
# ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
# endif
|
# endif
|
||||||
QHash<QString, QString>::ConstIterator it;
|
int id = idForFileName(fn, flags);
|
||||||
# ifdef PROEVALUATOR_DUAL_VFS
|
auto it = m_files.constFind(id);
|
||||||
it = m_files.constFind(((flags & VfsCumulative) ? '-' : '+') + fn);
|
|
||||||
if (it != m_files.constEnd())
|
|
||||||
return true;
|
|
||||||
# else
|
|
||||||
Q_UNUSED(flags)
|
|
||||||
# endif
|
|
||||||
it = m_files.constFind(fn);
|
|
||||||
if (it != m_files.constEnd())
|
if (it != m_files.constEnd())
|
||||||
return it->constData() != m_magicMissing.constData();
|
return it->constData() != m_magicMissing.constData();
|
||||||
#else
|
#else
|
||||||
@@ -221,7 +238,7 @@ bool QMakeVfs::exists(const QString &fn, VfsFlags flags)
|
|||||||
#endif
|
#endif
|
||||||
bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular;
|
bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular;
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
m_files[fn] = ex ? m_magicExisting : m_magicMissing;
|
m_files[id] = ex ? m_magicExisting : m_magicMissing;
|
||||||
#endif
|
#endif
|
||||||
return ex;
|
return ex;
|
||||||
}
|
}
|
||||||
@@ -233,7 +250,7 @@ void QMakeVfs::invalidateCache()
|
|||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
# ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
# endif
|
# endif
|
||||||
QHash<QString, QString>::Iterator it = m_files.begin(), eit = m_files.end();
|
auto it = m_files.begin(), eit = m_files.end();
|
||||||
while (it != eit) {
|
while (it != eit) {
|
||||||
if (it->constData() == m_magicMissing.constData()
|
if (it->constData() == m_magicMissing.constData()
|
||||||
||it->constData() == m_magicExisting.constData())
|
||it->constData() == m_magicExisting.constData())
|
||||||
|
@@ -27,13 +27,11 @@
|
|||||||
|
|
||||||
#include "qmake_global.h"
|
#include "qmake_global.h"
|
||||||
|
|
||||||
# include <qiodevice.h>
|
#include <qiodevice.h>
|
||||||
#ifndef PROEVALUATOR_FULL
|
#include <qhash.h>
|
||||||
# include <qhash.h>
|
#include <qstring.h>
|
||||||
# include <qstring.h>
|
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
# include <qmutex.h>
|
||||||
# include <qmutex.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef QT_NO_TEXTCODEC
|
#ifndef QT_NO_TEXTCODEC
|
||||||
@@ -62,23 +60,27 @@ public:
|
|||||||
VfsExact = 0,
|
VfsExact = 0,
|
||||||
#ifdef PROEVALUATOR_DUAL_VFS
|
#ifdef PROEVALUATOR_DUAL_VFS
|
||||||
VfsCumulative = 2,
|
VfsCumulative = 2,
|
||||||
VfsNoVirtual = 4
|
VfsCreate = 4,
|
||||||
|
VfsCreatedOnly = 8,
|
||||||
#else
|
#else
|
||||||
VfsCumulative = 0,
|
VfsCumulative = 0,
|
||||||
VfsNoVirtual = 0
|
VfsCreate = 0,
|
||||||
|
VfsCreatedOnly = 0,
|
||||||
#endif
|
#endif
|
||||||
|
VfsAccessedOnly = 16
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
|
Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
|
||||||
|
|
||||||
QMakeVfs();
|
QMakeVfs();
|
||||||
|
|
||||||
bool writeFile(const QString &fn, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
|
int idForFileName(const QString &fn, VfsFlags flags);
|
||||||
ReadResult readFile(const QString &fn, VfsFlags flags, QString *contents, QString *errStr);
|
QString fileNameForId(int id);
|
||||||
bool exists(const QString &fn, VfsFlags flags);
|
static void clearIds();
|
||||||
|
bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
|
||||||
|
ReadResult readFile(int id, QString *contents, QString *errStr);
|
||||||
|
bool exists(const QString &fn, QMakeVfs::VfsFlags flags);
|
||||||
|
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
bool readVirtualFile(const QString &fn, VfsFlags flags, QString *contents);
|
|
||||||
|
|
||||||
void invalidateCache();
|
void invalidateCache();
|
||||||
void invalidateContents();
|
void invalidateContents();
|
||||||
#endif
|
#endif
|
||||||
@@ -88,11 +90,34 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
|
static QMutex s_mutex;
|
||||||
|
#endif
|
||||||
|
static QAtomicInt s_fileIdCounter;
|
||||||
|
// Qt Creator's ProFile cache is a singleton to maximize its cross-project
|
||||||
|
// effectiveness (shared prf files from QtVersions).
|
||||||
|
// For this to actually work, real files need a global mapping.
|
||||||
|
// This is fine, because the namespace of real files is indeed global.
|
||||||
|
static QHash<QString, int> s_fileIdMap;
|
||||||
|
static QHash<int, QString> s_idFileMap;
|
||||||
|
#ifdef PROEVALUATOR_DUAL_VFS
|
||||||
|
# ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
|
// The simple way to avoid recursing m_mutex.
|
||||||
|
QMutex m_vmutex;
|
||||||
|
# endif
|
||||||
|
// Virtual files are bound to the project context they were created in,
|
||||||
|
// so their ids need to be local as well.
|
||||||
|
// We violate that rule in lupdate (which has a non-dual VFS), but that
|
||||||
|
// does not matter, because it has only one project context anyway.
|
||||||
|
QHash<QString, int> m_virtualFileIdMap[2]; // Exact and cumulative
|
||||||
|
QHash<int, QString> m_virtualIdFileMap; // Only one map, as ids are unique across realms.
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PROEVALUATOR_FULL
|
#ifndef PROEVALUATOR_FULL
|
||||||
# ifdef PROEVALUATOR_THREAD_SAFE
|
# ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
# endif
|
# endif
|
||||||
QHash<QString, QString> m_files;
|
QHash<int, QString> m_files;
|
||||||
QString m_magicMissing;
|
QString m_magicMissing;
|
||||||
QString m_magicExisting;
|
QString m_magicExisting;
|
||||||
#endif
|
#endif
|
||||||
|
Submodule src/shared/qbs updated: abfc4c1b37...2c0962017e
@@ -25,4 +25,5 @@ QtcAutotest {
|
|||||||
files: "tst_profilewriter.cpp"
|
files: "tst_profilewriter.cpp"
|
||||||
}
|
}
|
||||||
cpp.includePaths: base.concat([proParserGroup.prefix])
|
cpp.includePaths: base.concat([proParserGroup.prefix])
|
||||||
|
cpp.defines: base.concat("QT_USE_FAST_OPERATOR_PLUS")
|
||||||
}
|
}
|
||||||
|
@@ -448,7 +448,7 @@ void tst_ProFileWriter::adds()
|
|||||||
|
|
||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QMakeParser parser(0, &vfs, &parseHandler);
|
QMakeParser parser(0, &vfs, &parseHandler);
|
||||||
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1);
|
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
|
||||||
QVERIFY(proFile);
|
QVERIFY(proFile);
|
||||||
PW::putVarValues(proFile, &lines, values, var, PW::PutFlags(flags), scope);
|
PW::putVarValues(proFile, &lines, values, var, PW::PutFlags(flags), scope);
|
||||||
proFile->deref();
|
proFile->deref();
|
||||||
@@ -619,7 +619,7 @@ void tst_ProFileWriter::removes()
|
|||||||
|
|
||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QMakeParser parser(0, &vfs, &parseHandler);
|
QMakeParser parser(0, &vfs, &parseHandler);
|
||||||
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1);
|
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
|
||||||
QVERIFY(proFile);
|
QVERIFY(proFile);
|
||||||
QmakeProjectManager::Internal::ProWriter::removeVarValues(proFile, &lines, values, vars);
|
QmakeProjectManager::Internal::ProWriter::removeVarValues(proFile, &lines, values, vars);
|
||||||
proFile->deref();
|
proFile->deref();
|
||||||
@@ -648,7 +648,7 @@ void tst_ProFileWriter::multiVar()
|
|||||||
|
|
||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QMakeParser parser(0, &vfs, &parseHandler);
|
QMakeParser parser(0, &vfs, &parseHandler);
|
||||||
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1);
|
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
|
||||||
QVERIFY(proFile);
|
QVERIFY(proFile);
|
||||||
QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, baseDir, files, vars);
|
QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, baseDir, files, vars);
|
||||||
proFile->deref();
|
proFile->deref();
|
||||||
@@ -669,7 +669,7 @@ void tst_ProFileWriter::addFiles()
|
|||||||
|
|
||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QMakeParser parser(0, &vfs, &parseHandler);
|
QMakeParser parser(0, &vfs, &parseHandler);
|
||||||
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1);
|
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
|
||||||
QVERIFY(proFile);
|
QVERIFY(proFile);
|
||||||
QmakeProjectManager::Internal::ProWriter::addFiles(proFile, &lines,
|
QmakeProjectManager::Internal::ProWriter::addFiles(proFile, &lines,
|
||||||
QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"),
|
QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"),
|
||||||
@@ -691,7 +691,7 @@ void tst_ProFileWriter::removeFiles()
|
|||||||
|
|
||||||
QMakeVfs vfs;
|
QMakeVfs vfs;
|
||||||
QMakeParser parser(0, &vfs, &parseHandler);
|
QMakeParser parser(0, &vfs, &parseHandler);
|
||||||
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), QLatin1String(BASE_DIR "/test.pro"), 1);
|
ProFile *proFile = parser.parsedProBlock(QStringRef(&input), 0, QLatin1String(BASE_DIR "/test.pro"), 1);
|
||||||
QVERIFY(proFile);
|
QVERIFY(proFile);
|
||||||
QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, QDir(BASE_DIR),
|
QmakeProjectManager::Internal::ProWriter::removeFiles(proFile, &lines, QDir(BASE_DIR),
|
||||||
QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"),
|
QStringList() << QString::fromLatin1(BASE_DIR "/sub/bar.cpp"),
|
||||||
|
@@ -255,18 +255,9 @@ class JIRA:
|
|||||||
# for later lookup which function to call for which bug
|
# for later lookup which function to call for which bug
|
||||||
# ALWAYS update this dict when adding a new function for a workaround!
|
# ALWAYS update this dict when adding a new function for a workaround!
|
||||||
def __initBugDict__(self):
|
def __initBugDict__(self):
|
||||||
self.__bugs__= {
|
self.__bugs__= {}
|
||||||
'QTCREATORBUG-19717':self._workaroundCreator19717_,
|
|
||||||
}
|
|
||||||
# helper function - will be called if no workaround for the requested bug is deposited
|
# helper function - will be called if no workaround for the requested bug is deposited
|
||||||
def _exitFatal_(self, bugType, number):
|
def _exitFatal_(self, bugType, number):
|
||||||
test.fatal("No workaround found for bug %s-%d" % (bugType, number))
|
test.fatal("No workaround found for bug %s-%d" % (bugType, number))
|
||||||
|
|
||||||
############### functions that hold workarounds #################################
|
############### functions that hold workarounds #################################
|
||||||
|
|
||||||
def _workaroundCreator19717_(self, *args):
|
|
||||||
targetname = Targets.getStringForTarget(Targets.DESKTOP_5_3_1_DEFAULT)
|
|
||||||
switchViewTo(ViewConstants.PROJECTS)
|
|
||||||
mouseClick(waitForObjectItem(":Projects.ProjectNavigationTreeView",
|
|
||||||
"Build & Run." + targetname.replace(".", "\\.")))
|
|
||||||
switchViewTo(ViewConstants.EDIT)
|
|
||||||
|
@@ -124,8 +124,6 @@ def main():
|
|||||||
if not startedWithoutPluginError():
|
if not startedWithoutPluginError():
|
||||||
return
|
return
|
||||||
|
|
||||||
JIRA.performWorkaroundForBug(19717)
|
|
||||||
|
|
||||||
# if Debug is enabled - 1 valid kit is assigned - real check for this is done in tst_qml_locals
|
# if Debug is enabled - 1 valid kit is assigned - real check for this is done in tst_qml_locals
|
||||||
fancyDebugButton = waitForObject(":*Qt Creator.Start Debugging_Core::Internal::FancyToolButton")
|
fancyDebugButton = waitForObject(":*Qt Creator.Start Debugging_Core::Internal::FancyToolButton")
|
||||||
if test.verify(waitFor('fancyDebugButton.enabled', 5000), "Start Debugging is enabled."):
|
if test.verify(waitFor('fancyDebugButton.enabled', 5000), "Start Debugging is enabled."):
|
||||||
|
@@ -43,7 +43,6 @@ def main():
|
|||||||
startApplication('qtcreator' + SettingsPath + ' "%s"' % qmlProjFile)
|
startApplication('qtcreator' + SettingsPath + ' "%s"' % qmlProjFile)
|
||||||
if not startedWithoutPluginError():
|
if not startedWithoutPluginError():
|
||||||
return
|
return
|
||||||
JIRA.performWorkaroundForBug(19717)
|
|
||||||
waitFor('object.exists(":Qt Creator_Utils::NavigationTreeView")', 10000)
|
waitFor('object.exists(":Qt Creator_Utils::NavigationTreeView")', 10000)
|
||||||
fancyConfButton = findObject(":*Qt Creator_Core::Internal::FancyToolButton")
|
fancyConfButton = findObject(":*Qt Creator_Core::Internal::FancyToolButton")
|
||||||
fancyRunButton = findObject(":*Qt Creator.Run_Core::Internal::FancyToolButton")
|
fancyRunButton = findObject(":*Qt Creator.Run_Core::Internal::FancyToolButton")
|
||||||
|
@@ -25,10 +25,12 @@
|
|||||||
|
|
||||||
source("../../shared/qtcreator.py")
|
source("../../shared/qtcreator.py")
|
||||||
|
|
||||||
|
focusDocumentPath = "keyinteraction.Resources.keyinteraction\.qrc./keyinteraction.focus.%s"
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
target = Targets.DESKTOP_5_3_1_DEFAULT
|
target = Targets.DESKTOP_5_6_1_DEFAULT
|
||||||
sourceExample = os.path.join(Qt5Path.examplesPath(target), "declarative/keyinteraction/focus")
|
sourceExample = os.path.join(Qt5Path.examplesPath(target), "quick/keyinteraction")
|
||||||
proFile = "focus.pro"
|
proFile = "keyinteraction.pro"
|
||||||
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
if not neededFilePresent(os.path.join(sourceExample, proFile)):
|
||||||
return
|
return
|
||||||
startApplication("qtcreator" + SettingsPath)
|
startApplication("qtcreator" + SettingsPath)
|
||||||
@@ -36,9 +38,9 @@ def main():
|
|||||||
return
|
return
|
||||||
# add docs to have the correct tool tips
|
# add docs to have the correct tool tips
|
||||||
addHelpDocumentation([os.path.join(Qt5Path.docsPath(target), "qtquick.qch")])
|
addHelpDocumentation([os.path.join(Qt5Path.docsPath(target), "qtquick.qch")])
|
||||||
templateDir = prepareTemplate(sourceExample, "/../../helper")
|
templateDir = prepareTemplate(sourceExample)
|
||||||
openQmakeProject(os.path.join(templateDir, proFile), [target])
|
openQmakeProject(os.path.join(templateDir, proFile), [target])
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.focus\\.qml")
|
openDocument(focusDocumentPath % "focus\\.qml")
|
||||||
testRenameId()
|
testRenameId()
|
||||||
testFindUsages()
|
testFindUsages()
|
||||||
testHovering()
|
testHovering()
|
||||||
@@ -47,20 +49,20 @@ def main():
|
|||||||
|
|
||||||
def testRenameId():
|
def testRenameId():
|
||||||
test.log("Testing rename of id")
|
test.log("Testing rename of id")
|
||||||
files = ["FocusCore.ContextMenu\\.qml", "FocusCore.GridMenu\\.qml",
|
files = ["Core.ContextMenu\\.qml", "Core.GridMenu\\.qml",
|
||||||
"FocusCore.ListMenu\\.qml", "focus\\.qml"]
|
"Core.ListMenu\\.qml", "focus\\.qml"]
|
||||||
originalTexts = {}
|
originalTexts = {}
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
formerTxt = editor.plainText
|
formerTxt = editor.plainText
|
||||||
for file in files:
|
for file in files:
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.%s" % file)
|
openDocument(focusDocumentPath % file)
|
||||||
# wait until editor content switched to the double-clicked file
|
# wait until editor content switched to the double-clicked file
|
||||||
while formerTxt==editor.plainText:
|
while formerTxt==editor.plainText:
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
# store content for next round
|
# store content for next round
|
||||||
formerTxt = editor.plainText
|
formerTxt = editor.plainText
|
||||||
originalTexts.setdefault(file, "%s" % formerTxt)
|
originalTexts.setdefault(file, "%s" % formerTxt)
|
||||||
test.log("stored %s's content" % file.replace("FocusCore.","").replace("\\",""))
|
test.log("stored %s's content" % file.replace("Core.","").replace("\\",""))
|
||||||
# last opened file is the main file focus.qml
|
# last opened file is the main file focus.qml
|
||||||
line = "FocusScope\s*\{"
|
line = "FocusScope\s*\{"
|
||||||
if not placeCursorToLine(editor, line, True):
|
if not placeCursorToLine(editor, line, True):
|
||||||
@@ -77,18 +79,18 @@ def testRenameId():
|
|||||||
# store editor content for synchronizing purpose
|
# store editor content for synchronizing purpose
|
||||||
formerTxt = editor.plainText
|
formerTxt = editor.plainText
|
||||||
for file in files:
|
for file in files:
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.%s" % file)
|
openDocument(focusDocumentPath % file)
|
||||||
# wait until editor content switched to double-clicked file
|
# wait until editor content switched to double-clicked file
|
||||||
while formerTxt==editor.plainText:
|
while formerTxt==editor.plainText:
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
# store content for next round
|
# store content for next round
|
||||||
formerTxt = editor.plainText
|
formerTxt = editor.plainText
|
||||||
originalText = originalTexts.get(file).replace("mainView", "renamedView")
|
originalText = originalTexts.get(file).replace("mainView", "renamedView")
|
||||||
test.compare(originalText,formerTxt, "Comparing %s" % file.replace("FocusCore.","").replace("\\",""))
|
test.compare(originalText,formerTxt, "Comparing %s" % file.replace("Core.","").replace("\\",""))
|
||||||
invokeMenuItem("File","Save All")
|
invokeMenuItem("File","Save All")
|
||||||
|
|
||||||
def __invokeFindUsage__(filename, line, additionalKeyPresses, expectedCount):
|
def __invokeFindUsage__(filename, line, additionalKeyPresses, expectedCount):
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.%s" % filename)
|
openDocument(focusDocumentPath % filename)
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
if not placeCursorToLine(editor, line, True):
|
if not placeCursorToLine(editor, line, True):
|
||||||
test.fatal("File seems to have changed... Canceling current test")
|
test.fatal("File seems to have changed... Canceling current test")
|
||||||
@@ -101,17 +103,18 @@ def __invokeFindUsage__(filename, line, additionalKeyPresses, expectedCount):
|
|||||||
|
|
||||||
def testFindUsages():
|
def testFindUsages():
|
||||||
test.log("Testing find usage of an ID")
|
test.log("Testing find usage of an ID")
|
||||||
__invokeFindUsage__("focus\\.qml", "FocusScope\s*\{", ["<Down>"], 6)
|
__invokeFindUsage__("focus\\.qml", "FocusScope\s*\{", ["<Down>"], 7)
|
||||||
test.log("Testing find usage of a property")
|
test.log("Testing find usage of a property")
|
||||||
clickButton(waitForObject(":*Qt Creator.Clear_QToolButton"))
|
clickButton(waitForObject(":*Qt Creator.Clear_QToolButton"))
|
||||||
home = "<Home>"
|
home = "<Home>"
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
home = "<Ctrl+Left>"
|
home = "<Ctrl+Left>"
|
||||||
__invokeFindUsage__("focus\\.qml", "id: window", ["<Down>", "<Down>", home], 26)
|
__invokeFindUsage__("focus\\.qml", "id: window", ["<Down>", "<Down>", home],
|
||||||
|
29 if JIRA.isBugStillOpen(19915) else 30)
|
||||||
|
|
||||||
def testHovering():
|
def testHovering():
|
||||||
test.log("Testing hovering elements")
|
test.log("Testing hovering elements")
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.focus\\.qml")
|
openDocument(focusDocumentPath % "focus\\.qml")
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
lines=["FocusScope\s*\{", "Rectangle\s*\{"]
|
lines=["FocusScope\s*\{", "Rectangle\s*\{"]
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
@@ -129,7 +132,7 @@ def testHovering():
|
|||||||
alternativeValues = [{"text":"FocusScope"}, {"text":"Rectangle"}]
|
alternativeValues = [{"text":"FocusScope"}, {"text":"Rectangle"}]
|
||||||
verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues)
|
verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues)
|
||||||
test.log("Testing hovering properties")
|
test.log("Testing hovering properties")
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.focus\\.qml")
|
openDocument(focusDocumentPath % "focus\\.qml")
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
lines = ['focus:\s*true', 'color:\s*"black"', 'states:\s*State\s*\{', 'transitions:\s*Transition\s*\{']
|
lines = ['focus:\s*true', 'color:\s*"black"', 'states:\s*State\s*\{', 'transitions:\s*Transition\s*\{']
|
||||||
expectedTypes = ["TextTip", "TextTip", "TextTip", "TextTip"]
|
expectedTypes = ["TextTip", "TextTip", "TextTip", "TextTip"]
|
||||||
@@ -141,15 +144,19 @@ def testHovering():
|
|||||||
'></td></tr></table>'},
|
'></td></tr></table>'},
|
||||||
{'text':'<table><tr><td valign=middle>string<p>This property holds the color used to fill the rectangle.'
|
{'text':'<table><tr><td valign=middle>string<p>This property holds the color used to fill the rectangle.'
|
||||||
'</p></td><td> <img src=":/utils/tooltip/images/f1.png"></td></tr></table>'},
|
'</p></td><td> <img src=":/utils/tooltip/images/f1.png"></td></tr></table>'},
|
||||||
{'text':'<table><tr><td valign=middle>State<p>This property holds a list of states defined by the item.'
|
{'text':'<table><tr><td valign=middle>State<p>This property holds the list of possible states for this item. '
|
||||||
|
'To change the state of this item, set the state property to one of these states, or set the state property '
|
||||||
|
'to an empty string to revert the item to its default state.'
|
||||||
'</p></td><td> <img src=":/utils/tooltip/images/f1.png"></td></tr></table>'},
|
'</p></td><td> <img src=":/utils/tooltip/images/f1.png"></td></tr></table>'},
|
||||||
{'text':'<table><tr><td valign=middle>Transition<p>This property holds a list of transitions defined by '
|
{'text':'<table><tr><td valign=middle>Transition<p>This property holds the list of transitions for this item. '
|
||||||
'the item.</p></td><td> <img src=":/utils/tooltip/images/f1.png"></td></tr></table>'}
|
'These define the transitions to be applied to the item whenever it changes its state.'
|
||||||
|
'</p></td><td> <img src=":/utils/tooltip/images/f1.png"></td></tr></table>'}
|
||||||
]
|
]
|
||||||
alternativeValues = [{"text":"boolean"}, {"text":"string"}, {"text":"State"}, {"text":"Transition"}]
|
alternativeValues = [{"text":"Rectangle" if JIRA.isBugStillOpen(20020) else "boolean"},
|
||||||
|
{"text":"string"}, {"text":"State"}, {"text":"Transition"}]
|
||||||
verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues)
|
verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues)
|
||||||
test.log("Testing hovering expressions")
|
test.log("Testing hovering expressions")
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.focus\\.qml")
|
openDocument(focusDocumentPath % "focus\\.qml")
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
lines=['color:\s*"black"', 'color:\s*"#3E606F"']
|
lines=['color:\s*"black"', 'color:\s*"#3E606F"']
|
||||||
additionalKeyPresses = ["<Left>"]
|
additionalKeyPresses = ["<Left>"]
|
||||||
@@ -157,7 +164,7 @@ def testHovering():
|
|||||||
alternativeValues = [None, "#39616B"]
|
alternativeValues = [None, "#39616B"]
|
||||||
expectedTypes = ["ColorTip", "ColorTip"]
|
expectedTypes = ["ColorTip", "ColorTip"]
|
||||||
verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues)
|
verifyHoveringOnEditor(editor, lines, additionalKeyPresses, expectedTypes, expectedValues, alternativeValues)
|
||||||
openDocument("focus.QML.qml" + os.sep + "focus.FocusCore.ListMenu\\.qml")
|
openDocument(focusDocumentPath % "Core.ListMenu\\.qml")
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
lines=['Rectangle\s*\{.*color:\s*"#D1DBBD"', 'NumberAnimation\s*\{\s*.*Easing.OutQuint\s*\}']
|
lines=['Rectangle\s*\{.*color:\s*"#D1DBBD"', 'NumberAnimation\s*\{\s*.*Easing.OutQuint\s*\}']
|
||||||
additionalKeyPresses = ["<Left>", "<Left>", "<Left>", "<Left>"]
|
additionalKeyPresses = ["<Left>", "<Left>", "<Left>", "<Left>"]
|
||||||
|
@@ -26,9 +26,8 @@
|
|||||||
source("../../shared/qtcreator.py")
|
source("../../shared/qtcreator.py")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if platform.system() == 'Darwin':
|
test.warning("This needs a Qt 5.6.2 kit. Skipping it.")
|
||||||
test.warning("This needs a Qt 5.4 kit. Skipping it.")
|
return
|
||||||
return
|
|
||||||
pathCreator = os.path.join(srcPath, "creator", "qtcreator.qbs")
|
pathCreator = os.path.join(srcPath, "creator", "qtcreator.qbs")
|
||||||
if not neededFilePresent(pathCreator):
|
if not neededFilePresent(pathCreator):
|
||||||
return
|
return
|
||||||
|
@@ -101,8 +101,12 @@ def renameFile(projectDir, proFile, branch, oldname, newname):
|
|||||||
else:
|
else:
|
||||||
menu = ":Qt Creator.Project.Menu.File_QMenu"
|
menu = ":Qt Creator.Project.Menu.File_QMenu"
|
||||||
activateItem(waitForObjectItem(menu, "Rename..."))
|
activateItem(waitForObjectItem(menu, "Rename..."))
|
||||||
type(waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit"), newname)
|
replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit")
|
||||||
type(waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit"), "<Return>")
|
if not (oldname.lower().endswith(".qrc") and JIRA.isBugStillOpen(20057)):
|
||||||
|
test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0],
|
||||||
|
"Only the filename without the extension is selected?")
|
||||||
|
replaceEditorContent(replaceEdit, newname)
|
||||||
|
type(replaceEdit, "<Return>")
|
||||||
test.verify(waitFor("os.path.exists(newFilePath)", 1000),
|
test.verify(waitFor("os.path.exists(newFilePath)", 1000),
|
||||||
"Verify that file with new name exists: %s" % newFilePath)
|
"Verify that file with new name exists: %s" % newFilePath)
|
||||||
test.compare(readFile(newFilePath), oldFileText,
|
test.compare(readFile(newFilePath), oldFileText,
|
||||||
|
@@ -42,7 +42,7 @@ def main():
|
|||||||
test.fatal("Failed to activate kit %s" % kit)
|
test.fatal("Failed to activate kit %s" % kit)
|
||||||
continue
|
continue
|
||||||
test.log("Running project Qt Quick UI Prototype (%s)" % kit)
|
test.log("Running project Qt Quick UI Prototype (%s)" % kit)
|
||||||
qmlViewer = modifyRunSettingsForHookIntoQtQuickUI(1, 0, workingDir, projectName, 11223, quick)
|
qmlViewer = modifyRunSettingsForHookIntoQtQuickUI(2, 1, workingDir, projectName, 11223, quick)
|
||||||
if qmlViewer!=None:
|
if qmlViewer!=None:
|
||||||
qmlViewerPath = os.path.dirname(qmlViewer)
|
qmlViewerPath = os.path.dirname(qmlViewer)
|
||||||
qmlViewer = os.path.basename(qmlViewer)
|
qmlViewer = os.path.basename(qmlViewer)
|
||||||
|
Reference in New Issue
Block a user