forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/5.0'
Change-Id: I074571dac56b26a8a1449c29aef53b9052d8e304
This commit is contained in:
@@ -167,6 +167,26 @@ void registerNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
|
|||||||
QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(object, engine);
|
QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(object, engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isQuickStyleItemMetaObject(const QMetaObject *metaObject)
|
||||||
|
{
|
||||||
|
if (metaObject) {
|
||||||
|
if (metaObject->className() == QByteArrayLiteral("QQuickStyleItem"))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return isQuickStyleItemMetaObject(metaObject->superClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isQuickStyleItem(QObject *object)
|
||||||
|
{
|
||||||
|
if (object)
|
||||||
|
return isQuickStyleItemMetaObject(object->metaObject());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// This is used in share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
|
// This is used in share/qtcreator/qml/qmlpuppet/qml2puppet/instances/objectnodeinstance.cpp
|
||||||
QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
|
QObject *createPrimitive(const QString &typeName, int majorNumber, int minorNumber, QQmlContext *context)
|
||||||
{
|
{
|
||||||
@@ -357,14 +377,17 @@ void doComponentCompleteRecursive(QObject *object, NodeInstanceServer *nodeInsta
|
|||||||
doComponentCompleteRecursive(child, nodeInstanceServer);
|
doComponentCompleteRecursive(child, nodeInstanceServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isQuickStyleItem(item)) {
|
||||||
|
qDebug() << Q_FUNC_INFO << item;
|
||||||
if (item) {
|
if (item) {
|
||||||
static_cast<QQmlParserStatus*>(item)->componentComplete();
|
static_cast<QQmlParserStatus *>(item)->componentComplete();
|
||||||
} else {
|
} else {
|
||||||
QQmlParserStatus *qmlParserStatus = dynamic_cast< QQmlParserStatus*>(object);
|
QQmlParserStatus *qmlParserStatus = dynamic_cast<QQmlParserStatus *>(object);
|
||||||
if (qmlParserStatus)
|
if (qmlParserStatus)
|
||||||
qmlParserStatus->componentComplete();
|
qmlParserStatus->componentComplete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -413,7 +413,7 @@ SecondColumnLayout {
|
|||||||
id: transparentIndicator
|
id: transparentIndicator
|
||||||
icon: StudioTheme.Constants.transparent
|
icon: StudioTheme.Constants.transparent
|
||||||
pixelSize: StudioTheme.Values.myIconFontSize * 1.4
|
pixelSize: StudioTheme.Values.myIconFontSize * 1.4
|
||||||
tooltip: qsTr("Transparent TODO")
|
tooltip: qsTr("Transparent")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
colorPicker.alpha = 0
|
colorPicker.alpha = 0
|
||||||
colorPicker.updateColor()
|
colorPicker.updateColor()
|
||||||
@@ -575,22 +575,29 @@ SecondColumnLayout {
|
|||||||
onRightMouseButtonClicked: contextMenu.popup(colorPicker)
|
onRightMouseButtonClicked: contextMenu.popup(colorPicker)
|
||||||
|
|
||||||
onColorInvalidated: {
|
onColorInvalidated: {
|
||||||
if (colorPicker.saturation > 0.0 && colorPicker.lightness > 0.0) {
|
switch (colorPicker.mode) {
|
||||||
hueSpinBox.value = colorPicker.hue
|
case ColorPicker.Mode.HSLA:
|
||||||
}
|
hslHueSpinBox.value = colorPicker.hue
|
||||||
|
hslSaturationSpinBox.value = colorPicker.saturationHSL
|
||||||
if (colorPicker.lightness > 0.0)
|
hslLightnessSpinBox.value = colorPicker.lightness
|
||||||
saturationSpinBox.value = colorPicker.saturation
|
hslAlphaSpinBox.value = colorPicker.alpha
|
||||||
else
|
break
|
||||||
colorPicker.saturation = saturationSpinBox.value
|
|
||||||
|
|
||||||
lightnessSpinBox.value = colorPicker.lightness
|
|
||||||
hslaAlphaSpinBox.value = colorPicker.alpha
|
|
||||||
|
|
||||||
|
case ColorPicker.Mode.RGBA:
|
||||||
redSpinBox.value = (colorPicker.color.r * 255)
|
redSpinBox.value = (colorPicker.color.r * 255)
|
||||||
greenSpinBox.value = (colorPicker.color.g * 255)
|
greenSpinBox.value = (colorPicker.color.g * 255)
|
||||||
blueSpinBox.value = (colorPicker.color.b * 255)
|
blueSpinBox.value = (colorPicker.color.b * 255)
|
||||||
rgbaAlphaSpinBox.value = (colorPicker.alpha * 255)
|
rgbAlphaSpinBox.value = (colorPicker.alpha * 255)
|
||||||
|
break
|
||||||
|
|
||||||
|
case ColorPicker.Mode.HSVA:
|
||||||
|
default:
|
||||||
|
hsvHueSpinBox.value = colorPicker.hue
|
||||||
|
hsvSaturationSpinBox.value = colorPicker.saturationHSV
|
||||||
|
hsvValueSpinBox.value = colorPicker.value
|
||||||
|
hsvAlphaSpinBox.value = colorPicker.alpha
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -766,29 +773,22 @@ SecondColumnLayout {
|
|||||||
+ 4 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
+ 4 * StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
width: implicitWidth
|
width: implicitWidth
|
||||||
actionIndicatorVisible: false
|
actionIndicatorVisible: false
|
||||||
model: ["RGBA", "HSLA"]
|
textRole: "text"
|
||||||
onActivated: {
|
valueRole: "value"
|
||||||
switch (colorMode.currentText) {
|
model: [
|
||||||
case "RGBA":
|
{ value: ColorPicker.Mode.HSVA, text: "HSVA" },
|
||||||
rgbaRow.visible = true
|
{ value: ColorPicker.Mode.RGBA, text: "RGBA" },
|
||||||
hslaRow.visible = false
|
{ value: ColorPicker.Mode.HSLA, text: "HSLA" }
|
||||||
break
|
]
|
||||||
case "HSLA":
|
|
||||||
rgbaRow.visible = false
|
onActivated: colorPicker.mode = colorMode.currentValue
|
||||||
hslaRow.visible = true
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
console.log("Unknown color mode selected.")
|
|
||||||
rgbaRow.visible = true
|
|
||||||
hslaRow.visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: rgbaRow
|
id: rgbaRow
|
||||||
|
|
||||||
|
visible: colorPicker.mode === ColorPicker.Mode.RGBA
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: StudioTheme.Values.controlGap
|
spacing: StudioTheme.Values.controlGap
|
||||||
|
|
||||||
@@ -847,7 +847,7 @@ SecondColumnLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DoubleSpinBox {
|
DoubleSpinBox {
|
||||||
id: rgbaAlphaSpinBox
|
id: rgbAlphaSpinBox
|
||||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
|
|
||||||
stepSize: 1
|
stepSize: 1
|
||||||
@@ -856,7 +856,7 @@ SecondColumnLayout {
|
|||||||
decimals: 0
|
decimals: 0
|
||||||
|
|
||||||
onValueModified: {
|
onValueModified: {
|
||||||
var tmp = rgbaAlphaSpinBox.value / 255.0
|
var tmp = rgbAlphaSpinBox.value / 255.0
|
||||||
if (colorPicker.alpha !== tmp && !colorPicker.block) {
|
if (colorPicker.alpha !== tmp && !colorPicker.block) {
|
||||||
colorPicker.alpha = tmp
|
colorPicker.alpha = tmp
|
||||||
colorPicker.updateColor()
|
colorPicker.updateColor()
|
||||||
@@ -868,49 +868,109 @@ SecondColumnLayout {
|
|||||||
RowLayout {
|
RowLayout {
|
||||||
id: hslaRow
|
id: hslaRow
|
||||||
|
|
||||||
visible: false
|
visible: colorPicker.mode === ColorPicker.Mode.HSLA
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: StudioTheme.Values.controlGap
|
spacing: StudioTheme.Values.controlGap
|
||||||
|
|
||||||
DoubleSpinBox {
|
DoubleSpinBox {
|
||||||
id: hueSpinBox
|
id: hslHueSpinBox
|
||||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
onValueModified: {
|
onValueModified: {
|
||||||
if (colorPicker.hue !== hueSpinBox.value && !colorPicker.block) {
|
if (colorPicker.hue !== hslHueSpinBox.value
|
||||||
colorPicker.hue = hueSpinBox.value
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.hue = hslHueSpinBox.value
|
||||||
colorPicker.updateColor()
|
colorPicker.updateColor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DoubleSpinBox {
|
DoubleSpinBox {
|
||||||
id: saturationSpinBox
|
id: hslSaturationSpinBox
|
||||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
onValueModified: {
|
onValueModified: {
|
||||||
if (colorPicker.saturation !== saturationSpinBox.value && !colorPicker.block) {
|
if (colorPicker.saturationHSL !== hslSaturationSpinBox.value
|
||||||
colorPicker.saturation = saturationSpinBox.value
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.saturationHSL = hslSaturationSpinBox.value
|
||||||
colorPicker.updateColor()
|
colorPicker.updateColor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DoubleSpinBox {
|
DoubleSpinBox {
|
||||||
id: lightnessSpinBox
|
id: hslLightnessSpinBox
|
||||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
onValueModified: {
|
onValueModified: {
|
||||||
if (colorPicker.lightness !== lightnessSpinBox.value && !colorPicker.block) {
|
if (colorPicker.lightness !== hslLightnessSpinBox.value
|
||||||
colorPicker.lightness = lightnessSpinBox.value
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.lightness = hslLightnessSpinBox.value
|
||||||
colorPicker.updateColor()
|
colorPicker.updateColor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DoubleSpinBox {
|
DoubleSpinBox {
|
||||||
id: hslaAlphaSpinBox
|
id: hslAlphaSpinBox
|
||||||
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
onValueModified: {
|
onValueModified: {
|
||||||
if (colorPicker.alpha !== hslaAlphaSpinBox.value && !colorPicker.block) {
|
if (colorPicker.alpha !== hslAlphaSpinBox.value
|
||||||
colorPicker.alpha = hslaAlphaSpinBox.value
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.alpha = hslAlphaSpinBox.value
|
||||||
|
colorPicker.updateColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: hsvaRow
|
||||||
|
|
||||||
|
visible: colorPicker.mode === ColorPicker.Mode.HSVA
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: StudioTheme.Values.controlGap
|
||||||
|
|
||||||
|
DoubleSpinBox {
|
||||||
|
id: hsvHueSpinBox
|
||||||
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
|
onValueModified: {
|
||||||
|
if (colorPicker.hue !== hsvHueSpinBox.value
|
||||||
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.hue = hsvHueSpinBox.value
|
||||||
|
colorPicker.updateColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleSpinBox {
|
||||||
|
id: hsvSaturationSpinBox
|
||||||
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
|
onValueModified: {
|
||||||
|
if (colorPicker.saturationHSV !== hsvSaturationSpinBox.value
|
||||||
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.saturationHSV = hsvSaturationSpinBox.value
|
||||||
|
colorPicker.updateColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleSpinBox {
|
||||||
|
id: hsvValueSpinBox
|
||||||
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
|
onValueModified: {
|
||||||
|
if (colorPicker.value !== hsvValueSpinBox.value
|
||||||
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.value = hsvValueSpinBox.value
|
||||||
|
colorPicker.updateColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleSpinBox {
|
||||||
|
id: hsvAlphaSpinBox
|
||||||
|
width: StudioTheme.Values.colorEditorPopupSpinBoxWidth
|
||||||
|
onValueModified: {
|
||||||
|
if (colorPicker.alpha !== hsvAlphaSpinBox.value
|
||||||
|
&& !colorPicker.block) {
|
||||||
|
colorPicker.alpha = hsvAlphaSpinBox.value
|
||||||
colorPicker.updateColor()
|
colorPicker.updateColor()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,15 +29,26 @@ import StudioTheme 1.0 as StudioTheme
|
|||||||
Column {
|
Column {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
enum Mode {
|
||||||
|
HSVA,
|
||||||
|
RGBA,
|
||||||
|
HSLA
|
||||||
|
}
|
||||||
|
|
||||||
|
property int mode: ColorPicker.Mode.HSVA
|
||||||
property color color
|
property color color
|
||||||
property real alpha: 1
|
|
||||||
|
|
||||||
property real hue: 0
|
property real hue: 0
|
||||||
property real saturation: 0
|
property real saturationHSL: 0
|
||||||
|
property real saturationHSV: 0
|
||||||
property real lightness: 0
|
property real lightness: 0
|
||||||
|
property real value: 0
|
||||||
|
|
||||||
|
property real alpha: 1
|
||||||
|
|
||||||
|
property bool achromatic: false
|
||||||
|
|
||||||
property int sliderMargins: 6
|
property int sliderMargins: 6
|
||||||
|
|
||||||
property bool block: false
|
property bool block: false
|
||||||
|
|
||||||
signal updateColor
|
signal updateColor
|
||||||
@@ -46,30 +57,84 @@ Column {
|
|||||||
|
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
onAlphaChanged: invalidateColor()
|
onModeChanged: {
|
||||||
onSaturationChanged: invalidateColor()
|
switch (root.mode) {
|
||||||
onLightnessChanged: invalidateColor()
|
case ColorPicker.Mode.RGBA:
|
||||||
onHueChanged: invalidateColor()
|
root.color = Qt.rgba(root.color.r, root.color.g, root.color.b, root.alpha)
|
||||||
onColorChanged: {
|
break
|
||||||
var myAlpha = root.color.a
|
case ColorPicker.Mode.HSLA:
|
||||||
rgbToHsl(root.color)
|
root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha)
|
||||||
root.alpha = myAlpha
|
break
|
||||||
|
case ColorPicker.Mode.HSVA:
|
||||||
|
default:
|
||||||
|
root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gradientOverlay.requestPaint()
|
||||||
|
}
|
||||||
|
|
||||||
|
onHueChanged: {
|
||||||
|
if (root.mode === ColorPicker.Mode.HSLA)
|
||||||
|
root.color.hslHue = root.hue
|
||||||
|
else
|
||||||
|
root.color.hsvHue = root.hue
|
||||||
|
}
|
||||||
|
onSaturationHSLChanged: {
|
||||||
|
root.color.hslSaturation = root.saturationHSL
|
||||||
|
invalidateColor()
|
||||||
|
}
|
||||||
|
onSaturationHSVChanged: {
|
||||||
|
root.color.hsvSaturation = root.saturationHSV
|
||||||
|
}
|
||||||
|
onLightnessChanged: {
|
||||||
|
root.color.hslLightness = root.lightness
|
||||||
|
}
|
||||||
|
onValueChanged: {
|
||||||
|
root.color.hsvValue = root.value
|
||||||
|
}
|
||||||
|
onAlphaChanged: invalidateColor()
|
||||||
|
onColorChanged: invalidateColor()
|
||||||
|
|
||||||
function invalidateColor() {
|
function invalidateColor() {
|
||||||
if (root.block)
|
if (root.block)
|
||||||
return
|
return
|
||||||
|
|
||||||
root.block = true
|
root.block = true
|
||||||
|
|
||||||
root.color = Qt.hsla(root.hue,
|
if (root.color.hsvSaturation > 0.0
|
||||||
root.saturation,
|
&& root.color.hsvValue > 0.0
|
||||||
root.lightness,
|
&& root.color.hsvHue !== -1.0)
|
||||||
root.alpha)
|
root.hue = root.color.hsvHue
|
||||||
|
|
||||||
if (root.saturation > 0.0 && root.lightness > 0.0)
|
if (root.color.hslSaturation > 0.0
|
||||||
|
&& root.color.hslLightness > 0.0
|
||||||
|
&& root.color.hslHue !== -1.0)
|
||||||
|
root.hue = root.color.hslHue
|
||||||
|
|
||||||
|
if (root.color.hslLightness !== 0.0 && root.color.hslLightness !== 1.0 && !root.achromatic)
|
||||||
|
root.saturationHSL = root.color.hslSaturation
|
||||||
|
|
||||||
|
if (root.color.hsvValue !== 0.0 && root.color.hsvValue !== 1.0 && !root.achromatic)
|
||||||
|
root.saturationHSV = root.color.hsvSaturation
|
||||||
|
|
||||||
|
root.lightness = root.color.hslLightness
|
||||||
|
root.value = root.color.hsvValue
|
||||||
|
|
||||||
|
if (root.color.hslLightness === 0.0 || root.color.hslLightness === 1.0
|
||||||
|
|| root.color.hsvValue === 0.0 || root.color.hsvValue === 1.0
|
||||||
|
|| root.color.hsvHue === -1.0 || root.color.hslHue === -1.0)
|
||||||
|
root.achromatic = true
|
||||||
|
else
|
||||||
|
root.achromatic = false
|
||||||
|
|
||||||
|
if (root.mode === ColorPicker.Mode.HSLA)
|
||||||
|
root.color = Qt.hsla(root.hue, root.saturationHSL, root.lightness, root.alpha)
|
||||||
|
else
|
||||||
|
root.color = Qt.hsva(root.hue, root.saturationHSV, root.value, root.alpha)
|
||||||
|
|
||||||
|
luminanceSlider.value = (1.0 - root.value)
|
||||||
hueSlider.value = root.hue
|
hueSlider.value = root.hue
|
||||||
|
|
||||||
opacitySlider.value = (1.0 - root.alpha)
|
opacitySlider.value = (1.0 - root.alpha)
|
||||||
|
|
||||||
root.colorInvalidated()
|
root.colorInvalidated()
|
||||||
@@ -77,39 +142,51 @@ Column {
|
|||||||
root.block = false
|
root.block = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function rgbToHsl(color) {
|
function drawHSVA(ctx) {
|
||||||
var r = color.r
|
for (var row = 0; row < gradientOverlay.height; row++) {
|
||||||
var g = color.g
|
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
|
||||||
var b = color.b
|
var v = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
|
||||||
|
|
||||||
var max = Math.max(r, g, b), min = Math.min(r, g, b)
|
gradient.addColorStop(0, Qt.hsva(root.hue, 0, v, 1))
|
||||||
var h, s, l = (max + min) / 2
|
gradient.addColorStop(1, Qt.hsva(root.hue, 1, v, 1))
|
||||||
|
|
||||||
if (max === min) {
|
ctx.fillStyle = gradient
|
||||||
h = 0
|
ctx.fillRect(0, row, gradientOverlay.width, 1)
|
||||||
s = 0
|
}
|
||||||
} else {
|
|
||||||
var d = max - min
|
|
||||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
|
|
||||||
switch (max) {
|
|
||||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
||||||
case g: h = (b - r) / d + 2; break;
|
|
||||||
case b: h = (r - g) / d + 4; break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h /= 6
|
function drawRGBA(ctx) {
|
||||||
|
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
|
||||||
|
gradient.addColorStop(0.000, Qt.rgba(1, 0, 0, 1))
|
||||||
|
gradient.addColorStop(0.167, Qt.rgba(1, 1, 0, 1))
|
||||||
|
gradient.addColorStop(0.333, Qt.rgba(0, 1, 0, 1))
|
||||||
|
gradient.addColorStop(0.500, Qt.rgba(0, 1, 1, 1))
|
||||||
|
gradient.addColorStop(0.667, Qt.rgba(0, 0, 1, 1))
|
||||||
|
gradient.addColorStop(0.833, Qt.rgba(1, 0, 1, 1))
|
||||||
|
gradient.addColorStop(1.000, Qt.rgba(1, 0, 0, 1))
|
||||||
|
|
||||||
|
ctx.fillStyle = gradient
|
||||||
|
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
||||||
|
|
||||||
|
gradient = ctx.createLinearGradient(0, 0, 0, gradientOverlay.height)
|
||||||
|
gradient.addColorStop(0.000, Qt.rgba(0, 0, 0, 0))
|
||||||
|
gradient.addColorStop(1.000, Qt.rgba(1, 1, 1, 1))
|
||||||
|
|
||||||
|
ctx.fillStyle = gradient
|
||||||
|
ctx.fillRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
||||||
}
|
}
|
||||||
|
|
||||||
root.block = true
|
function drawHSLA(ctx) {
|
||||||
|
for (var row = 0; row < gradientOverlay.height; row++) {
|
||||||
|
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width, 0)
|
||||||
|
var l = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
|
||||||
|
|
||||||
if (s > 0)
|
gradient.addColorStop(0, Qt.hsla(root.hue, 0, l, 1))
|
||||||
root.hue = h
|
gradient.addColorStop(1, Qt.hsla(root.hue, 1, l, 1))
|
||||||
|
|
||||||
root.saturation = s
|
ctx.fillStyle = gradient
|
||||||
root.lightness = l
|
ctx.fillRect(0, row, gradientOverlay.width, 1)
|
||||||
|
}
|
||||||
root.block = false
|
|
||||||
invalidateColor()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -133,26 +210,30 @@ Column {
|
|||||||
Canvas {
|
Canvas {
|
||||||
id: gradientOverlay
|
id: gradientOverlay
|
||||||
|
|
||||||
property real hue: root.hue
|
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
opacity: root.alpha
|
opacity: root.color.a
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
function onHueChanged() { gradientOverlay.requestPaint() }
|
||||||
|
}
|
||||||
|
|
||||||
onHueChanged: requestPaint()
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
var ctx = gradientOverlay.getContext('2d')
|
var ctx = gradientOverlay.getContext('2d')
|
||||||
ctx.save()
|
ctx.save()
|
||||||
ctx.clearRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
ctx.clearRect(0, 0, gradientOverlay.width, gradientOverlay.height)
|
||||||
|
|
||||||
for (var row = 0; row < gradientOverlay.height; row++) {
|
switch (root.mode) {
|
||||||
var gradient = ctx.createLinearGradient(0, 0, gradientOverlay.width,0)
|
case ColorPicker.Mode.RGBA:
|
||||||
var l = Math.abs(row - gradientOverlay.height) / gradientOverlay.height
|
root.drawRGBA(ctx)
|
||||||
|
break
|
||||||
gradient.addColorStop(0, Qt.hsla(gradientOverlay.hue, 0, l, 1))
|
case ColorPicker.Mode.HSLA:
|
||||||
gradient.addColorStop(1, Qt.hsla(gradientOverlay.hue, 1, l, 1))
|
root.drawHSLA(ctx)
|
||||||
|
break
|
||||||
ctx.fillStyle = gradient
|
case ColorPicker.Mode.HSVA:
|
||||||
ctx.fillRect(0, row, gradientOverlay.width, 1)
|
default:
|
||||||
|
root.drawHSVA(ctx)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.restore()
|
ctx.restore()
|
||||||
@@ -162,25 +243,41 @@ Column {
|
|||||||
Canvas {
|
Canvas {
|
||||||
id: pickerCross
|
id: pickerCross
|
||||||
|
|
||||||
property real cavnasSaturation: root.saturation
|
|
||||||
property real canvasLightness: root.lightness
|
|
||||||
property color strokeStyle: "lightGray"
|
property color strokeStyle: "lightGray"
|
||||||
|
|
||||||
opacity: 0.8
|
opacity: 0.8
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
|
|
||||||
onCavnasSaturationChanged: requestPaint();
|
Connections {
|
||||||
onCanvasLightnessChanged: requestPaint();
|
target: root
|
||||||
|
function onColorInvalidated() { pickerCross.requestPaint() }
|
||||||
|
function onColorChanged() { pickerCross.requestPaint() }
|
||||||
|
function onModeChanged() { pickerCross.requestPaint() }
|
||||||
|
}
|
||||||
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
var ctx = pickerCross.getContext('2d')
|
var ctx = pickerCross.getContext('2d')
|
||||||
|
|
||||||
ctx.save()
|
ctx.save()
|
||||||
|
|
||||||
ctx.clearRect(0, 0, pickerCross.width, pickerCross.height)
|
ctx.clearRect(0, 0, pickerCross.width, pickerCross.height)
|
||||||
|
|
||||||
var yy = pickerCross.height -root.lightness * pickerCross.height
|
var yy, xx = 0
|
||||||
var xx = root.saturation * pickerCross.width
|
|
||||||
|
switch (root.mode) {
|
||||||
|
case ColorPicker.Mode.RGBA:
|
||||||
|
yy = pickerCross.height - root.saturationHSV * pickerCross.height
|
||||||
|
xx = root.hue * pickerCross.width
|
||||||
|
break
|
||||||
|
case ColorPicker.Mode.HSLA:
|
||||||
|
yy = pickerCross.height - root.lightness * pickerCross.height
|
||||||
|
xx = root.saturationHSL * pickerCross.width
|
||||||
|
break
|
||||||
|
case ColorPicker.Mode.HSVA:
|
||||||
|
default:
|
||||||
|
yy = pickerCross.height - root.value * pickerCross.height
|
||||||
|
xx = root.saturationHSV * pickerCross.width
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
ctx.strokeStyle = pickerCross.strokeStyle
|
ctx.strokeStyle = pickerCross.strokeStyle
|
||||||
ctx.lineWidth = 1
|
ctx.lineWidth = 1
|
||||||
@@ -200,24 +297,37 @@ Column {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mapMouseArea
|
id: mouseArea
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
|
||||||
onPositionChanged: function(mouse) {
|
onPositionChanged: function(mouse) {
|
||||||
if (pressed && mouse.buttons === Qt.LeftButton) {
|
if (mouseArea.pressed && mouse.buttons === Qt.LeftButton) {
|
||||||
var xx = Math.max(0, Math.min(mouse.x, parent.width))
|
var xx = Math.max(0, Math.min(mouse.x, parent.width))
|
||||||
var yy = Math.max(0, Math.min(mouse.y, parent.height))
|
var yy = Math.max(0, Math.min(mouse.y, parent.height))
|
||||||
|
|
||||||
|
switch (root.mode) {
|
||||||
|
case ColorPicker.Mode.RGBA:
|
||||||
|
root.saturationHSV = 1.0 - yy / parent.height
|
||||||
|
root.hue = xx / parent.width
|
||||||
|
break
|
||||||
|
case ColorPicker.Mode.HSLA:
|
||||||
|
root.saturationHSL = xx / parent.width
|
||||||
root.lightness = 1.0 - yy / parent.height
|
root.lightness = 1.0 - yy / parent.height
|
||||||
root.saturation = xx / parent.width
|
break
|
||||||
|
case ColorPicker.Mode.HSVA:
|
||||||
|
default:
|
||||||
|
root.saturationHSV = xx / parent.width
|
||||||
|
root.value = 1.0 - yy / parent.height
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPressed: function(mouse) {
|
onPressed: function(mouse) {
|
||||||
if (mouse.button === Qt.LeftButton)
|
if (mouse.button === Qt.LeftButton)
|
||||||
positionChanged(mouse)
|
mouseArea.positionChanged(mouse)
|
||||||
}
|
}
|
||||||
onReleased: function(mouse) {
|
onReleased: function(mouse) {
|
||||||
if (mouse.button === Qt.LeftButton)
|
if (mouse.button === Qt.LeftButton)
|
||||||
@@ -233,10 +343,23 @@ Column {
|
|||||||
|
|
||||||
HueSlider {
|
HueSlider {
|
||||||
id: hueSlider
|
id: hueSlider
|
||||||
|
visible: root.mode !== ColorPicker.Mode.RGBA
|
||||||
width: parent.width
|
width: parent.width
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
if (root.hue !== value)
|
if (root.hue !== hueSlider.value)
|
||||||
root.hue = value
|
root.hue = hueSlider.value
|
||||||
|
}
|
||||||
|
onClicked: root.updateColor()
|
||||||
|
}
|
||||||
|
|
||||||
|
LuminanceSlider {
|
||||||
|
id: luminanceSlider
|
||||||
|
visible: root.mode === ColorPicker.Mode.RGBA
|
||||||
|
width: parent.width
|
||||||
|
color: Qt.hsva(root.hue, root.color.hsvSaturation, 1, 1)
|
||||||
|
onValueChanged: {
|
||||||
|
if (root.value !== luminanceSlider.value)
|
||||||
|
root.value = (1.0 - luminanceSlider.value)
|
||||||
}
|
}
|
||||||
onClicked: root.updateColor()
|
onClicked: root.updateColor()
|
||||||
}
|
}
|
||||||
@@ -246,8 +369,8 @@ Column {
|
|||||||
width: parent.width
|
width: parent.width
|
||||||
color: Qt.rgba(root.color.r, root.color.g, root.color.b, 1)
|
color: Qt.rgba(root.color.r, root.color.g, root.color.b, 1)
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
if (root.alpha !== value)
|
if (root.alpha !== opacitySlider.value)
|
||||||
root.alpha = (1.0 - value)
|
root.alpha = (1.0 - opacitySlider.value)
|
||||||
}
|
}
|
||||||
onClicked: root.updateColor()
|
onClicked: root.updateColor()
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,121 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
import QtQuick 2.15
|
||||||
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property real value: 1
|
||||||
|
property real minimum: 0
|
||||||
|
property real maximum: 1
|
||||||
|
property bool pressed: mouseArea.pressed
|
||||||
|
property bool integer: false
|
||||||
|
property color color
|
||||||
|
|
||||||
|
signal clicked
|
||||||
|
|
||||||
|
height: StudioTheme.Values.hueSliderHeight
|
||||||
|
|
||||||
|
function updatePos() {
|
||||||
|
if (root.maximum > root.minimum) {
|
||||||
|
var pos = (track.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum)
|
||||||
|
return Math.min(Math.max(pos, 0), track.width - handle.width)
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: track
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: checkerboard
|
||||||
|
anchors.fill: parent
|
||||||
|
source: "images/checkers.png"
|
||||||
|
fillMode: Image.Tile
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
border.color: StudioTheme.Values.themeControlOutline
|
||||||
|
border.width: StudioTheme.Values.border
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Horizontal
|
||||||
|
GradientStop { position: 0.000; color: root.color }
|
||||||
|
GradientStop { position: 1.000; color: "black" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: handle
|
||||||
|
width: StudioTheme.Values.hueSliderHandleWidth
|
||||||
|
height: track.height - 4
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
smooth: true
|
||||||
|
color: "transparent"
|
||||||
|
radius: 2
|
||||||
|
border.color: "black"
|
||||||
|
border.width: 1
|
||||||
|
x: root.updatePos()
|
||||||
|
y: 2
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 1
|
||||||
|
color: "transparent"
|
||||||
|
radius: 1
|
||||||
|
border.color: "white"
|
||||||
|
border.width: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
preventStealing: true
|
||||||
|
|
||||||
|
function calculateValue() {
|
||||||
|
var handleX = Math.max(0, Math.min(mouseArea.mouseX, mouseArea.width))
|
||||||
|
var realValue = (root.maximum - root.minimum) * handleX / mouseArea.width + root.minimum
|
||||||
|
root.value = root.integer ? Math.round(realValue) : realValue
|
||||||
|
}
|
||||||
|
|
||||||
|
onPressed: calculateValue()
|
||||||
|
onReleased: root.clicked()
|
||||||
|
onPositionChanged: {
|
||||||
|
if (pressed)
|
||||||
|
calculateValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -45,6 +45,7 @@ Label 2.0 Label.qml
|
|||||||
LineEdit 2.0 LineEdit.qml
|
LineEdit 2.0 LineEdit.qml
|
||||||
LinkIndicator2D 2.0 LinkIndicator2D.qml
|
LinkIndicator2D 2.0 LinkIndicator2D.qml
|
||||||
ListViewComboBox 2.0 ListViewComboBox.qml
|
ListViewComboBox 2.0 ListViewComboBox.qml
|
||||||
|
LuminanceSlider 2.0 LuminanceSlider.qml
|
||||||
MarginSection 2.0 MarginSection.qml
|
MarginSection 2.0 MarginSection.qml
|
||||||
MultiIconLabel 2.0 MultiIconLabel.qml
|
MultiIconLabel 2.0 MultiIconLabel.qml
|
||||||
OpacitySlider 2.0 OpacitySlider.qml
|
OpacitySlider 2.0 OpacitySlider.qml
|
||||||
|
@@ -52,6 +52,7 @@ add_qtc_library(Utils
|
|||||||
filecrumblabel.cpp filecrumblabel.h
|
filecrumblabel.cpp filecrumblabel.h
|
||||||
fileinprojectfinder.cpp fileinprojectfinder.h
|
fileinprojectfinder.cpp fileinprojectfinder.h
|
||||||
filenamevalidatinglineedit.cpp filenamevalidatinglineedit.h
|
filenamevalidatinglineedit.cpp filenamevalidatinglineedit.h
|
||||||
|
filepath.cpp filepath.h
|
||||||
filesearch.cpp filesearch.h
|
filesearch.cpp filesearch.h
|
||||||
filesystemwatcher.cpp filesystemwatcher.h
|
filesystemwatcher.cpp filesystemwatcher.h
|
||||||
fileutils.cpp fileutils.h
|
fileutils.cpp fileutils.h
|
||||||
|
1295
src/libs/utils/filepath.cpp
Normal file
1295
src/libs/utils/filepath.cpp
Normal file
File diff suppressed because it is too large
Load Diff
193
src/libs/utils/filepath.h
Normal file
193
src/libs/utils/filepath.h
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 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 "utils_global.h"
|
||||||
|
|
||||||
|
#include "hostosinfo.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QDateTime;
|
||||||
|
class QDebug;
|
||||||
|
class QFileInfo;
|
||||||
|
class QUrl;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class tst_fileutils; // This becomes a friend of Utils::FilePath for testing private methods.
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
|
||||||
|
class Environment;
|
||||||
|
|
||||||
|
class QTCREATOR_UTILS_EXPORT FilePath
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FilePath();
|
||||||
|
|
||||||
|
static FilePath fromString(const QString &filepath);
|
||||||
|
static FilePath fromFileInfo(const QFileInfo &info);
|
||||||
|
static FilePath fromStringWithExtension(const QString &filepath, const QString &defaultExtension);
|
||||||
|
static FilePath fromUserInput(const QString &filepath);
|
||||||
|
static FilePath fromUtf8(const char *filepath, int filepathSize = -1);
|
||||||
|
static FilePath fromVariant(const QVariant &variant);
|
||||||
|
|
||||||
|
QString toString() const;
|
||||||
|
FilePath onDevice(const FilePath &deviceTemplate) const;
|
||||||
|
FilePath withNewPath(const QString &newPath) const;
|
||||||
|
|
||||||
|
QFileInfo toFileInfo() const;
|
||||||
|
QVariant toVariant() const;
|
||||||
|
QDir toDir() const;
|
||||||
|
|
||||||
|
QString toUserOutput() const;
|
||||||
|
QString shortNativePath() const;
|
||||||
|
|
||||||
|
QString fileName() const;
|
||||||
|
QString fileNameWithPathComponents(int pathComponents) const;
|
||||||
|
|
||||||
|
QString baseName() const;
|
||||||
|
QString completeBaseName() const;
|
||||||
|
QString suffix() const;
|
||||||
|
QString completeSuffix() const;
|
||||||
|
|
||||||
|
QString scheme() const { return m_scheme; }
|
||||||
|
void setScheme(const QString &scheme);
|
||||||
|
|
||||||
|
QString host() const { return m_host; }
|
||||||
|
void setHost(const QString &host);
|
||||||
|
|
||||||
|
QString path() const { return m_data; }
|
||||||
|
void setPath(const QString &path) { m_data = path; }
|
||||||
|
|
||||||
|
bool needsDevice() const;
|
||||||
|
bool exists() const;
|
||||||
|
|
||||||
|
bool isWritablePath() const { return isWritableDir(); } // Remove.
|
||||||
|
bool isWritableDir() const;
|
||||||
|
bool isWritableFile() const;
|
||||||
|
bool ensureWritableDir() const;
|
||||||
|
bool ensureExistingFile() const;
|
||||||
|
bool isExecutableFile() const;
|
||||||
|
bool isReadableFile() const;
|
||||||
|
bool isReadableDir() const;
|
||||||
|
bool isRelativePath() const;
|
||||||
|
bool isAbsolutePath() const { return !isRelativePath(); }
|
||||||
|
bool isFile() const;
|
||||||
|
bool isDir() const;
|
||||||
|
|
||||||
|
bool createDir() const;
|
||||||
|
QList<FilePath> dirEntries(const QStringList &nameFilters,
|
||||||
|
QDir::Filters filters,
|
||||||
|
QDir::SortFlags sort = QDir::NoSort) const;
|
||||||
|
QList<FilePath> dirEntries(QDir::Filters filters) const;
|
||||||
|
QByteArray fileContents(qint64 maxSize = -1, qint64 offset = 0) const;
|
||||||
|
bool writeFileContents(const QByteArray &data) const;
|
||||||
|
|
||||||
|
FilePath parentDir() const;
|
||||||
|
FilePath absolutePath() const;
|
||||||
|
FilePath absoluteFilePath() const;
|
||||||
|
FilePath absoluteFilePath(const FilePath &tail) const;
|
||||||
|
FilePath absoluteFromRelativePath(const FilePath &anchor) const;
|
||||||
|
|
||||||
|
bool operator==(const FilePath &other) const;
|
||||||
|
bool operator!=(const FilePath &other) const;
|
||||||
|
bool operator<(const FilePath &other) const;
|
||||||
|
bool operator<=(const FilePath &other) const;
|
||||||
|
bool operator>(const FilePath &other) const;
|
||||||
|
bool operator>=(const FilePath &other) const;
|
||||||
|
FilePath operator+(const QString &s) const;
|
||||||
|
|
||||||
|
bool isChildOf(const FilePath &s) const;
|
||||||
|
bool isChildOf(const QDir &dir) const;
|
||||||
|
bool startsWith(const QString &s) const;
|
||||||
|
bool endsWith(const QString &s) const;
|
||||||
|
|
||||||
|
bool isNewerThan(const QDateTime &timeStamp) const;
|
||||||
|
QDateTime lastModified() const;
|
||||||
|
QFile::Permissions permissions() const;
|
||||||
|
OsType osType() const;
|
||||||
|
bool removeFile() const;
|
||||||
|
bool removeRecursively(QString *error = nullptr) const;
|
||||||
|
bool copyFile(const FilePath &target) const;
|
||||||
|
bool renameFile(const FilePath &target) const;
|
||||||
|
|
||||||
|
Qt::CaseSensitivity caseSensitivity() const;
|
||||||
|
|
||||||
|
FilePath relativeChildPath(const FilePath &parent) const;
|
||||||
|
FilePath relativePath(const FilePath &anchor) const;
|
||||||
|
FilePath pathAppended(const QString &str) const;
|
||||||
|
FilePath stringAppended(const QString &str) const;
|
||||||
|
FilePath resolvePath(const QString &fileName) const;
|
||||||
|
FilePath cleanPath() const;
|
||||||
|
|
||||||
|
FilePath canonicalPath() const;
|
||||||
|
FilePath symLinkTarget() const;
|
||||||
|
FilePath resolveSymlinks() const;
|
||||||
|
FilePath withExecutableSuffix() const;
|
||||||
|
|
||||||
|
FilePath operator/(const QString &str) const;
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
bool isEmpty() const;
|
||||||
|
|
||||||
|
uint hash(uint seed) const;
|
||||||
|
|
||||||
|
// NOTE: Most FilePath operations on FilePath created from URL currently
|
||||||
|
// do not work. Among the working are .toVariant() and .toUrl().
|
||||||
|
static FilePath fromUrl(const QUrl &url);
|
||||||
|
QUrl toUrl() const;
|
||||||
|
|
||||||
|
FilePath searchOnDevice(const QList<FilePath> &dirs) const;
|
||||||
|
Environment deviceEnvironment() const;
|
||||||
|
|
||||||
|
static QString formatFilePaths(const QList<FilePath> &files, const QString &separator);
|
||||||
|
static void removeDuplicates(QList<FilePath> &files);
|
||||||
|
static void sort(QList<FilePath> &files);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ::tst_fileutils;
|
||||||
|
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
|
||||||
|
|
||||||
|
QString m_scheme;
|
||||||
|
QString m_host;
|
||||||
|
QString m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
using FilePaths = QList<FilePath>;
|
||||||
|
|
||||||
|
} // namespace Utils
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FilePath &c);
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Utils::FilePath)
|
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include "filepath.h"
|
||||||
#include "hostosinfo.h"
|
#include "hostosinfo.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -40,33 +41,17 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Utils {
|
|
||||||
class Environment;
|
|
||||||
class FilePath;
|
|
||||||
} // Utils
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QDataStream;
|
class QDataStream;
|
||||||
class QDateTime;
|
|
||||||
class QDir;
|
|
||||||
class QFile;
|
|
||||||
class QFileInfo;
|
|
||||||
class QTemporaryFile;
|
|
||||||
class QTextStream;
|
class QTextStream;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug dbg, const Utils::FilePath &c);
|
|
||||||
|
|
||||||
// for withNtfsPermissions
|
// for withNtfsPermissions
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
|
extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
// tst_fileutils becomes a friend of Utils::FilePath for testing private method
|
|
||||||
class tst_fileutils;
|
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
class DeviceFileHooks
|
class DeviceFileHooks
|
||||||
@@ -99,152 +84,6 @@ public:
|
|||||||
std::function<Environment(const FilePath &)> environment;
|
std::function<Environment(const FilePath &)> environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT FilePath
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FilePath();
|
|
||||||
|
|
||||||
static FilePath fromString(const QString &filepath);
|
|
||||||
static FilePath fromFileInfo(const QFileInfo &info);
|
|
||||||
static FilePath fromStringWithExtension(const QString &filepath, const QString &defaultExtension);
|
|
||||||
static FilePath fromUserInput(const QString &filepath);
|
|
||||||
static FilePath fromUtf8(const char *filepath, int filepathSize = -1);
|
|
||||||
static FilePath fromVariant(const QVariant &variant);
|
|
||||||
|
|
||||||
QString toString() const;
|
|
||||||
FilePath onDevice(const FilePath &deviceTemplate) const;
|
|
||||||
FilePath withNewPath(const QString &newPath) const;
|
|
||||||
|
|
||||||
QFileInfo toFileInfo() const;
|
|
||||||
QVariant toVariant() const;
|
|
||||||
QDir toDir() const;
|
|
||||||
|
|
||||||
QString toUserOutput() const;
|
|
||||||
QString shortNativePath() const;
|
|
||||||
|
|
||||||
QString fileName() const;
|
|
||||||
QString fileNameWithPathComponents(int pathComponents) const;
|
|
||||||
|
|
||||||
QString baseName() const;
|
|
||||||
QString completeBaseName() const;
|
|
||||||
QString suffix() const;
|
|
||||||
QString completeSuffix() const;
|
|
||||||
|
|
||||||
QString scheme() const { return m_scheme; }
|
|
||||||
void setScheme(const QString &scheme);
|
|
||||||
|
|
||||||
QString host() const { return m_host; }
|
|
||||||
void setHost(const QString &host);
|
|
||||||
|
|
||||||
QString path() const { return m_data; }
|
|
||||||
void setPath(const QString &path) { m_data = path; }
|
|
||||||
|
|
||||||
bool needsDevice() const;
|
|
||||||
bool exists() const;
|
|
||||||
|
|
||||||
bool isWritablePath() const { return isWritableDir(); } // Remove.
|
|
||||||
bool isWritableDir() const;
|
|
||||||
bool isWritableFile() const;
|
|
||||||
bool ensureWritableDir() const;
|
|
||||||
bool ensureExistingFile() const;
|
|
||||||
bool isExecutableFile() const;
|
|
||||||
bool isReadableFile() const;
|
|
||||||
bool isReadableDir() const;
|
|
||||||
bool isRelativePath() const;
|
|
||||||
bool isAbsolutePath() const { return !isRelativePath(); }
|
|
||||||
bool isFile() const;
|
|
||||||
bool isDir() const;
|
|
||||||
|
|
||||||
bool createDir() const;
|
|
||||||
QList<FilePath> dirEntries(const QStringList &nameFilters,
|
|
||||||
QDir::Filters filters,
|
|
||||||
QDir::SortFlags sort = QDir::NoSort) const;
|
|
||||||
QList<FilePath> dirEntries(QDir::Filters filters) const;
|
|
||||||
QByteArray fileContents(qint64 maxSize = -1, qint64 offset = 0) const;
|
|
||||||
bool writeFileContents(const QByteArray &data) const;
|
|
||||||
|
|
||||||
FilePath parentDir() const;
|
|
||||||
FilePath absolutePath() const;
|
|
||||||
FilePath absoluteFilePath() const;
|
|
||||||
FilePath absoluteFilePath(const FilePath &tail) const;
|
|
||||||
FilePath absoluteFromRelativePath(const FilePath &anchor) const;
|
|
||||||
|
|
||||||
bool operator==(const FilePath &other) const;
|
|
||||||
bool operator!=(const FilePath &other) const;
|
|
||||||
bool operator<(const FilePath &other) const;
|
|
||||||
bool operator<=(const FilePath &other) const;
|
|
||||||
bool operator>(const FilePath &other) const;
|
|
||||||
bool operator>=(const FilePath &other) const;
|
|
||||||
FilePath operator+(const QString &s) const;
|
|
||||||
|
|
||||||
bool isChildOf(const FilePath &s) const;
|
|
||||||
bool isChildOf(const QDir &dir) const;
|
|
||||||
bool startsWith(const QString &s) const;
|
|
||||||
bool endsWith(const QString &s) const;
|
|
||||||
|
|
||||||
bool isNewerThan(const QDateTime &timeStamp) const;
|
|
||||||
QDateTime lastModified() const;
|
|
||||||
QFile::Permissions permissions() const;
|
|
||||||
OsType osType() const;
|
|
||||||
bool removeFile() const;
|
|
||||||
bool removeRecursively(QString *error = nullptr) const;
|
|
||||||
bool copyFile(const FilePath &target) const;
|
|
||||||
bool renameFile(const FilePath &target) const;
|
|
||||||
|
|
||||||
Qt::CaseSensitivity caseSensitivity() const;
|
|
||||||
|
|
||||||
FilePath relativeChildPath(const FilePath &parent) const;
|
|
||||||
FilePath relativePath(const FilePath &anchor) const;
|
|
||||||
FilePath pathAppended(const QString &str) const;
|
|
||||||
FilePath stringAppended(const QString &str) const;
|
|
||||||
FilePath resolvePath(const QString &fileName) const;
|
|
||||||
FilePath resolveSymlinkTarget() const;
|
|
||||||
FilePath cleanPath() const;
|
|
||||||
|
|
||||||
FilePath canonicalPath() const;
|
|
||||||
FilePath symLinkTarget() const;
|
|
||||||
FilePath resolveSymlinks() const;
|
|
||||||
FilePath withExecutableSuffix() const;
|
|
||||||
|
|
||||||
FilePath operator/(const QString &str) const;
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
bool isEmpty() const;
|
|
||||||
|
|
||||||
uint hash(uint seed) const;
|
|
||||||
|
|
||||||
// NOTE: Most FilePath operations on FilePath created from URL currently
|
|
||||||
// do not work. Among the working are .toVariant() and .toUrl().
|
|
||||||
static FilePath fromUrl(const QUrl &url);
|
|
||||||
QUrl toUrl() const;
|
|
||||||
|
|
||||||
static void setDeviceFileHooks(const DeviceFileHooks &hooks);
|
|
||||||
|
|
||||||
FilePath searchOnDevice(const QList<FilePath> &dirs) const;
|
|
||||||
Environment deviceEnvironment() const;
|
|
||||||
|
|
||||||
static QString formatFilePaths(const QList<FilePath> &files, const QString &separator);
|
|
||||||
static void removeDuplicates(QList<FilePath> &files);
|
|
||||||
static void sort(QList<FilePath> &files);
|
|
||||||
|
|
||||||
static QList<FilePath> filterEntriesHelper(const FilePath &base,
|
|
||||||
const QStringList &entries,
|
|
||||||
const QStringList &nameFilters,
|
|
||||||
QDir::Filters filters,
|
|
||||||
QDir::SortFlags sort);
|
|
||||||
private:
|
|
||||||
friend class ::tst_fileutils;
|
|
||||||
static QString calcRelativePath(const QString &absolutePath, const QString &absoluteAnchorPath);
|
|
||||||
|
|
||||||
QString m_scheme;
|
|
||||||
QString m_host;
|
|
||||||
QString m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FilePath &fn);
|
|
||||||
|
|
||||||
using FilePaths = QList<FilePath>;
|
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT FileUtils {
|
class QTCREATOR_UTILS_EXPORT FileUtils {
|
||||||
public:
|
public:
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
@@ -287,6 +126,8 @@ public:
|
|||||||
static QByteArray fileId(const FilePath &fileName);
|
static QByteArray fileId(const FilePath &fileName);
|
||||||
static FilePath homePath();
|
static FilePath homePath();
|
||||||
static bool renameFile(const FilePath &srcFilePath, const FilePath &tgtFilePath);
|
static bool renameFile(const FilePath &srcFilePath, const FilePath &tgtFilePath);
|
||||||
|
|
||||||
|
static void setDeviceFileHooks(const DeviceFileHooks &hooks);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -432,6 +273,8 @@ private:
|
|||||||
bool m_autoRemove = true;
|
bool m_autoRemove = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QTCREATOR_UTILS_EXPORT QTextStream &operator<<(QTextStream &s, const FilePath &fn);
|
||||||
|
|
||||||
inline uint qHash(const Utils::FilePath &a, uint seed = 0) { return a.hash(seed); }
|
inline uint qHash(const Utils::FilePath &a, uint seed = 0) { return a.hash(seed); }
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
@@ -445,4 +288,3 @@ template<> struct QTCREATOR_UTILS_EXPORT hash<Utils::FilePath>
|
|||||||
};
|
};
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Utils::FilePath)
|
|
||||||
|
@@ -554,7 +554,13 @@ void QtcProcess::start()
|
|||||||
{
|
{
|
||||||
d->clearForRun();
|
d->clearForRun();
|
||||||
|
|
||||||
QTC_CHECK(d->m_writeData.isEmpty()); // FIXME: Use it.
|
if (!d->m_writeData.isEmpty()) {
|
||||||
|
connect(d->m_process, &ProcessInterface::started, this, [this] {
|
||||||
|
const qint64 bytesWritten = write(d->m_writeData);
|
||||||
|
QTC_CHECK(bytesWritten == d->m_writeData.size());
|
||||||
|
closeWriteChannel(); // FIXME: Is this good?
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (d->m_commandLine.executable().needsDevice()) {
|
if (d->m_commandLine.executable().needsDevice()) {
|
||||||
QTC_ASSERT(s_deviceHooks.startProcessHook, return);
|
QTC_ASSERT(s_deviceHooks.startProcessHook, return);
|
||||||
@@ -1219,6 +1225,7 @@ void QtcProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter)
|
|||||||
void QtcProcess::setWriteData(const QByteArray &writeData)
|
void QtcProcess::setWriteData(const QByteArray &writeData)
|
||||||
{
|
{
|
||||||
d->m_writeData = writeData;
|
d->m_writeData = writeData;
|
||||||
|
setKeepWriteChannelOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QT_GUI_LIB
|
#ifdef QT_GUI_LIB
|
||||||
@@ -1231,11 +1238,9 @@ static bool isGuiThread()
|
|||||||
void QtcProcess::runBlocking()
|
void QtcProcess::runBlocking()
|
||||||
{
|
{
|
||||||
// FIXME: Implement properly
|
// FIXME: Implement properly
|
||||||
|
|
||||||
if (d->m_commandLine.executable().needsDevice()) {
|
if (d->m_commandLine.executable().needsDevice()) {
|
||||||
|
|
||||||
// writeData ?
|
|
||||||
QtcProcess::start();
|
QtcProcess::start();
|
||||||
|
|
||||||
waitForFinished();
|
waitForFinished();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@@ -62,6 +62,7 @@ SOURCES += \
|
|||||||
$$PWD/fancylineedit.cpp \
|
$$PWD/fancylineedit.cpp \
|
||||||
$$PWD/qtcolorbutton.cpp \
|
$$PWD/qtcolorbutton.cpp \
|
||||||
$$PWD/savefile.cpp \
|
$$PWD/savefile.cpp \
|
||||||
|
$$PWD/filepath.cpp \
|
||||||
$$PWD/fileutils.cpp \
|
$$PWD/fileutils.cpp \
|
||||||
$$PWD/textfileformat.cpp \
|
$$PWD/textfileformat.cpp \
|
||||||
$$PWD/consoleprocess.cpp \
|
$$PWD/consoleprocess.cpp \
|
||||||
@@ -196,6 +197,7 @@ HEADERS += \
|
|||||||
$$PWD/qtcolorbutton.h \
|
$$PWD/qtcolorbutton.h \
|
||||||
$$PWD/consoleprocess.h \
|
$$PWD/consoleprocess.h \
|
||||||
$$PWD/savefile.h \
|
$$PWD/savefile.h \
|
||||||
|
$$PWD/filepath.h \
|
||||||
$$PWD/fileutils.h \
|
$$PWD/fileutils.h \
|
||||||
$$PWD/textfileformat.h \
|
$$PWD/textfileformat.h \
|
||||||
$$PWD/uncommentselection.h \
|
$$PWD/uncommentselection.h \
|
||||||
|
@@ -115,6 +115,8 @@ Project {
|
|||||||
"fileinprojectfinder.h",
|
"fileinprojectfinder.h",
|
||||||
"filenamevalidatinglineedit.cpp",
|
"filenamevalidatinglineedit.cpp",
|
||||||
"filenamevalidatinglineedit.h",
|
"filenamevalidatinglineedit.h",
|
||||||
|
"filepath.cpp",
|
||||||
|
"filepath.h",
|
||||||
"filesearch.cpp",
|
"filesearch.cpp",
|
||||||
"filesearch.h",
|
"filesearch.h",
|
||||||
"filesystemwatcher.cpp",
|
"filesystemwatcher.cpp",
|
||||||
|
@@ -1066,13 +1066,20 @@ AndroidDeviceInfo AndroidConfigurations::showDeviceDialog(Project *project,
|
|||||||
if (!serialNumber.isEmpty())
|
if (!serialNumber.isEmpty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AndroidDeviceInfo defaultDevice = AndroidDeviceDialog::defaultDeviceInfo(serialNumber);
|
||||||
|
if (defaultDevice.isValid())
|
||||||
|
return defaultDevice;
|
||||||
|
|
||||||
AndroidDeviceDialog dialog(apiLevel, abis, serialNumber, Core::ICore::dialogParent());
|
AndroidDeviceDialog dialog(apiLevel, abis, serialNumber, Core::ICore::dialogParent());
|
||||||
AndroidDeviceInfo info = dialog.device();
|
AndroidDeviceInfo info = dialog.showAndGetSelectedDevice();
|
||||||
if (dialog.saveDeviceSelection() && info.isValid()) {
|
if (dialog.saveDeviceSelection() && info.isValid()) {
|
||||||
const QString serialNumber = info.type == AndroidDeviceInfo::Hardware ?
|
const QString newSerialNumber = info.type == AndroidDeviceInfo::Hardware ?
|
||||||
info.serialNumber : info.avdname;
|
info.serialNumber : info.avdname;
|
||||||
if (!serialNumber.isEmpty())
|
if (!newSerialNumber.isEmpty()) {
|
||||||
AndroidConfigurations::setDefaultDevice(project, AndroidManager::devicePreferredAbi(info.cpuAbi, abis), serialNumber);
|
const QString preferredAbi = AndroidManager::devicePreferredAbi(info.cpuAbi, abis);
|
||||||
|
AndroidConfigurations::setDefaultDevice(project, preferredAbi, newSerialNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,8 @@ using namespace Android::Internal;
|
|||||||
namespace Android {
|
namespace Android {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
QVector<AndroidDeviceInfo> AndroidDeviceDialog::m_connectedDevices = {};
|
||||||
|
|
||||||
// yeah, writing tree models is fun!
|
// yeah, writing tree models is fun!
|
||||||
class AndroidDeviceModelNode
|
class AndroidDeviceModelNode
|
||||||
{
|
{
|
||||||
@@ -481,26 +483,30 @@ AndroidDeviceDialog::~AndroidDeviceDialog()
|
|||||||
delete m_ui;
|
delete m_ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidDeviceInfo AndroidDeviceDialog::device()
|
AndroidDeviceInfo AndroidDeviceDialog::defaultDeviceInfo(const QString &serialNumber)
|
||||||
{
|
{
|
||||||
refreshDeviceList();
|
AndroidDeviceDialog::updateConnectedDevicesList();
|
||||||
|
|
||||||
if (!m_defaultDevice.isEmpty()) {
|
if (serialNumber.isEmpty())
|
||||||
auto device = std::find_if(m_connectedDevices.cbegin(),
|
return {};
|
||||||
m_connectedDevices.cend(),
|
|
||||||
[this](const AndroidDeviceInfo &info) {
|
return Utils::findOrDefault(m_connectedDevices, [serialNumber](const AndroidDeviceInfo &info) {
|
||||||
return info.serialNumber == m_defaultDevice ||
|
return info.serialNumber == serialNumber || info.avdname == serialNumber;
|
||||||
info.avdname == m_defaultDevice;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (device != m_connectedDevices.cend())
|
AndroidDeviceInfo AndroidDeviceDialog::showAndGetSelectedDevice()
|
||||||
return *device;
|
{
|
||||||
m_defaultDevice.clear();
|
auto dev = defaultDeviceInfo(m_defaultDevice);
|
||||||
}
|
if (dev.isValid())
|
||||||
|
return dev;
|
||||||
|
|
||||||
|
refreshDeviceList();
|
||||||
|
|
||||||
if (exec() == QDialog::Accepted)
|
if (exec() == QDialog::Accepted)
|
||||||
return m_model->device(m_ui->deviceView->currentIndex());
|
return m_model->device(m_ui->deviceView->currentIndex());
|
||||||
return AndroidDeviceInfo();
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AndroidDeviceDialog::saveDeviceSelection() const
|
bool AndroidDeviceDialog::saveDeviceSelection() const
|
||||||
@@ -508,11 +514,16 @@ bool AndroidDeviceDialog::saveDeviceSelection() const
|
|||||||
return m_ui->defaultDeviceCheckBox->isChecked();
|
return m_ui->defaultDeviceCheckBox->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidDeviceDialog::updateConnectedDevicesList()
|
||||||
|
{
|
||||||
|
m_connectedDevices = AndroidConfig::connectedDevices(AndroidConfigurations::currentConfig()
|
||||||
|
.adbToolPath());
|
||||||
|
}
|
||||||
|
|
||||||
void AndroidDeviceDialog::refreshDeviceList()
|
void AndroidDeviceDialog::refreshDeviceList()
|
||||||
{
|
{
|
||||||
m_ui->refreshDevicesButton->setEnabled(false);
|
m_ui->refreshDevicesButton->setEnabled(false);
|
||||||
m_progressIndicator->show();
|
m_progressIndicator->show();
|
||||||
m_connectedDevices = AndroidConfig::connectedDevices(AndroidConfigurations::currentConfig().adbToolPath());
|
|
||||||
m_futureWatcherRefreshDevices.setFuture(m_avdManager->avdList());
|
m_futureWatcherRefreshDevices.setFuture(m_avdManager->avdList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -56,7 +56,8 @@ public:
|
|||||||
const QString &serialNumber, QWidget *parent = nullptr);
|
const QString &serialNumber, QWidget *parent = nullptr);
|
||||||
~AndroidDeviceDialog() override;
|
~AndroidDeviceDialog() override;
|
||||||
|
|
||||||
AndroidDeviceInfo device();
|
AndroidDeviceInfo showAndGetSelectedDevice();
|
||||||
|
static AndroidDeviceInfo defaultDeviceInfo(const QString &serialNumber);
|
||||||
|
|
||||||
bool saveDeviceSelection() const;
|
bool saveDeviceSelection() const;
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ private:
|
|||||||
void devicesRefreshed();
|
void devicesRefreshed();
|
||||||
void enableOkayButton();
|
void enableOkayButton();
|
||||||
void defaultDeviceClear();
|
void defaultDeviceClear();
|
||||||
|
static void updateConnectedDevicesList();
|
||||||
|
|
||||||
AndroidDeviceModel *m_model;
|
AndroidDeviceModel *m_model;
|
||||||
Ui::AndroidDeviceDialog *m_ui;
|
Ui::AndroidDeviceDialog *m_ui;
|
||||||
@@ -76,8 +78,8 @@ private:
|
|||||||
QStringList m_abis;
|
QStringList m_abis;
|
||||||
QString m_avdNameFromAdd;
|
QString m_avdNameFromAdd;
|
||||||
QString m_defaultDevice;
|
QString m_defaultDevice;
|
||||||
|
static QVector<AndroidDeviceInfo> m_connectedDevices;
|
||||||
std::unique_ptr<AndroidAvdManager> m_avdManager;
|
std::unique_ptr<AndroidAvdManager> m_avdManager;
|
||||||
QVector<AndroidDeviceInfo> m_connectedDevices;
|
|
||||||
QFutureWatcher<CreateAvdInfo> m_futureWatcherAddDevice;
|
QFutureWatcher<CreateAvdInfo> m_futureWatcherAddDevice;
|
||||||
QFutureWatcher<AndroidDeviceInfoList> m_futureWatcherRefreshDevices;
|
QFutureWatcher<AndroidDeviceInfoList> m_futureWatcherRefreshDevices;
|
||||||
};
|
};
|
||||||
|
@@ -515,7 +515,7 @@ void CMakeBuildSettingsWidget::batchEditConfiguration()
|
|||||||
[expander](const QString &s) {
|
[expander](const QString &s) {
|
||||||
return expander->expand(s);
|
return expander->expand(s);
|
||||||
});
|
});
|
||||||
const CMakeConfig config = CMakeConfigItem::itemsFromArguments(expandedLines);
|
const CMakeConfig config = CMakeConfig::fromArguments(expandedLines);
|
||||||
|
|
||||||
m_configModel->setBatchEditConfiguration(config);
|
m_configModel->setBatchEditConfiguration(config);
|
||||||
});
|
});
|
||||||
@@ -1048,7 +1048,7 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map)
|
|||||||
}();
|
}();
|
||||||
if (initialCMakeArguments().isEmpty()) {
|
if (initialCMakeArguments().isEmpty()) {
|
||||||
QStringList initialArgs = defaultInitialCMakeArguments(kit(), buildTypeName)
|
QStringList initialArgs = defaultInitialCMakeArguments(kit(), buildTypeName)
|
||||||
+ Utils::transform(conf, [this](const CMakeConfigItem &i) {
|
+ Utils::transform(conf.toList(), [this](const CMakeConfigItem &i) {
|
||||||
return i.toArgument(macroExpander());
|
return i.toArgument(macroExpander());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1110,7 +1110,8 @@ CMakeConfig CMakeBuildConfiguration::configurationChanges() const
|
|||||||
|
|
||||||
QStringList CMakeBuildConfiguration::configurationChangesArguments() const
|
QStringList CMakeBuildConfiguration::configurationChangesArguments() const
|
||||||
{
|
{
|
||||||
return Utils::transform(m_configurationChanges, [](const CMakeConfigItem &i) { return i.toArgument(); });
|
return Utils::transform(m_configurationChanges.toList(),
|
||||||
|
[](const CMakeConfigItem &i) { return i.toArgument(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CMakeBuildConfiguration::initialCMakeArguments() const
|
QStringList CMakeBuildConfiguration::initialCMakeArguments() const
|
||||||
@@ -1296,9 +1297,9 @@ BuildInfo CMakeBuildConfigurationFactory::createBuildInfo(BuildType buildType)
|
|||||||
|
|
||||||
BuildConfiguration::BuildType CMakeBuildConfiguration::buildType() const
|
BuildConfiguration::BuildType CMakeBuildConfiguration::buildType() const
|
||||||
{
|
{
|
||||||
QByteArray cmakeBuildTypeName = CMakeConfigItem::valueOf("CMAKE_BUILD_TYPE", m_configurationFromCMake);
|
QByteArray cmakeBuildTypeName = m_configurationFromCMake.valueOf("CMAKE_BUILD_TYPE");
|
||||||
if (cmakeBuildTypeName.isEmpty()) {
|
if (cmakeBuildTypeName.isEmpty()) {
|
||||||
QByteArray cmakeCfgTypes = CMakeConfigItem::valueOf("CMAKE_CONFIGURATION_TYPES", m_configurationFromCMake);
|
QByteArray cmakeCfgTypes = m_configurationFromCMake.valueOf("CMAKE_CONFIGURATION_TYPES");
|
||||||
if (!cmakeCfgTypes.isEmpty())
|
if (!cmakeCfgTypes.isEmpty())
|
||||||
cmakeBuildTypeName = cmakeBuildType().toUtf8();
|
cmakeBuildTypeName = cmakeBuildType().toUtf8();
|
||||||
}
|
}
|
||||||
@@ -1352,14 +1353,14 @@ QString CMakeBuildConfiguration::cmakeBuildType() const
|
|||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
config = CMakeBuildSystem::parseCMakeCacheDotTxt(cmakeCacheTxt, &errorMessage);
|
config = CMakeBuildSystem::parseCMakeCacheDotTxt(cmakeCacheTxt, &errorMessage);
|
||||||
} else {
|
} else {
|
||||||
config = CMakeConfigItem::itemsFromArguments(initialCMakeArguments());
|
config = CMakeConfig::fromArguments(initialCMakeArguments());
|
||||||
}
|
}
|
||||||
} else if (!hasCMakeCache) {
|
} else if (!hasCMakeCache) {
|
||||||
config = CMakeConfigItem::itemsFromArguments(initialCMakeArguments());
|
config = CMakeConfig::fromArguments(initialCMakeArguments());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.isEmpty() && !isMultiConfig()) {
|
if (!config.isEmpty() && !isMultiConfig()) {
|
||||||
cmakeBuildType = CMakeConfigItem::stringValueOf("CMAKE_BUILD_TYPE", config);
|
cmakeBuildType = config.stringValueOf("CMAKE_BUILD_TYPE");
|
||||||
const_cast<CMakeBuildConfiguration*>(this)->setCMakeBuildType(cmakeBuildType);
|
const_cast<CMakeBuildConfiguration*>(this)->setCMakeBuildType(cmakeBuildType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -838,7 +838,7 @@ void CMakeBuildSystem::wireUpConnections()
|
|||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
const CMakeConfig config = CMakeBuildSystem::parseCMakeCacheDotTxt(cmakeCacheTxt, &errorMessage);
|
const CMakeConfig config = CMakeBuildSystem::parseCMakeCacheDotTxt(cmakeCacheTxt, &errorMessage);
|
||||||
if (!config.isEmpty() && errorMessage.isEmpty()) {
|
if (!config.isEmpty() && errorMessage.isEmpty()) {
|
||||||
QString cmakeBuildTypeName = CMakeConfigItem::stringValueOf("CMAKE_BUILD_TYPE", config);
|
QString cmakeBuildTypeName = config.stringValueOf("CMAKE_BUILD_TYPE");
|
||||||
cmakeBuildConfiguration()->setCMakeBuildType(cmakeBuildTypeName, true);
|
cmakeBuildConfiguration()->setCMakeBuildType(cmakeBuildTypeName, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1057,7 +1057,7 @@ CMakeConfig CMakeBuildSystem::parseCMakeCacheDotTxt(const Utils::FilePath &cache
|
|||||||
*errorMessage = tr("CMakeCache.txt file not found.");
|
*errorMessage = tr("CMakeCache.txt file not found.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
CMakeConfig result = CMakeConfigItem::itemsFromFile(cacheFile, errorMessage);
|
CMakeConfig result = CMakeConfig::fromFile(cacheFile, errorMessage);
|
||||||
if (!errorMessage->isEmpty())
|
if (!errorMessage->isEmpty())
|
||||||
return {};
|
return {};
|
||||||
return result;
|
return result;
|
||||||
@@ -1210,7 +1210,7 @@ void CMakeBuildSystem::updateQmlJSCodeModel(const QStringList &extraHeaderPaths,
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CMakeConfig &cm = cmakeBuildConfiguration()->configurationFromCMake();
|
const CMakeConfig &cm = cmakeBuildConfiguration()->configurationFromCMake();
|
||||||
addImports(CMakeConfigItem::stringValueOf("QML_IMPORT_PATH", cm));
|
addImports(cm.stringValueOf("QML_IMPORT_PATH"));
|
||||||
addImports(kit()->value(QtSupport::KitQmlImportPath::id()).toString());
|
addImports(kit()->value(QtSupport::KitQmlImportPath::id()).toString());
|
||||||
|
|
||||||
for (const QString &extraHeaderPath : extraHeaderPaths)
|
for (const QString &extraHeaderPath : extraHeaderPaths)
|
||||||
@@ -1244,7 +1244,7 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars()
|
|||||||
{
|
{
|
||||||
const CMakeConfig &cm = cmakeBuildConfiguration()->configurationFromCMake();
|
const CMakeConfig &cm = cmakeBuildConfiguration()->configurationFromCMake();
|
||||||
const CMakeConfig &initialConfig =
|
const CMakeConfig &initialConfig =
|
||||||
CMakeConfigItem::itemsFromArguments(cmakeBuildConfiguration()->initialCMakeArguments());
|
CMakeConfig::fromArguments(cmakeBuildConfiguration()->initialCMakeArguments());
|
||||||
|
|
||||||
CMakeConfig config;
|
CMakeConfig config;
|
||||||
|
|
||||||
@@ -1275,7 +1275,7 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars()
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (it != cm.cend()) {
|
if (it != cm.cend()) {
|
||||||
const QByteArray initialValue = CMakeConfigItem::expandedValueOf(kit(), var, initialConfig).toUtf8();
|
const QByteArray initialValue = initialConfig.expandedValueOf(kit(), var).toUtf8();
|
||||||
const FilePath initialPath = FilePath::fromString(QString::fromUtf8(initialValue));
|
const FilePath initialPath = FilePath::fromString(QString::fromUtf8(initialValue));
|
||||||
const FilePath path = FilePath::fromString(QString::fromUtf8(it->value));
|
const FilePath path = FilePath::fromString(QString::fromUtf8(it->value));
|
||||||
|
|
||||||
@@ -1299,7 +1299,9 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars()
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (it != cm.cend()) {
|
if (it != cm.cend()) {
|
||||||
const QByteArray initialValue = CMakeConfigItem::expandedValueOf(kit(), var, initialConfig).toUtf8();
|
const QByteArrayList initialValueList = initialConfig.expandedValueOf(kit(), var).toUtf8().split(';');
|
||||||
|
|
||||||
|
for (const auto &initialValue: initialValueList) {
|
||||||
const FilePath initialPath = FilePath::fromString(QString::fromUtf8(initialValue));
|
const FilePath initialPath = FilePath::fromString(QString::fromUtf8(initialValue));
|
||||||
|
|
||||||
const bool pathIsContained
|
const bool pathIsContained
|
||||||
@@ -1316,6 +1318,7 @@ void CMakeBuildSystem::updateInitialCMakeExpandableVars()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!config.isEmpty())
|
if (!config.isEmpty())
|
||||||
emit cmakeBuildConfiguration()->configurationChanged(config);
|
emit cmakeBuildConfiguration()->configurationChanged(config);
|
||||||
|
@@ -55,29 +55,28 @@ CMakeConfigItem::CMakeConfigItem(const QByteArray &k, const QByteArray &v) :
|
|||||||
key(k), value(v)
|
key(k), value(v)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
QByteArray CMakeConfigItem::valueOf(const QByteArray &key, const QList<CMakeConfigItem> &input)
|
QByteArray CMakeConfig::valueOf(const QByteArray &key) const
|
||||||
{
|
{
|
||||||
for (auto it = input.constBegin(); it != input.constEnd(); ++it) {
|
for (auto it = constBegin(); it != constEnd(); ++it) {
|
||||||
if (it->key == key)
|
if (it->key == key)
|
||||||
return it->value;
|
return it->value;
|
||||||
}
|
}
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CMakeConfigItem::stringValueOf(const QByteArray &key, const QList<CMakeConfigItem> &input)
|
QString CMakeConfig::stringValueOf(const QByteArray &key) const
|
||||||
{
|
{
|
||||||
return QString::fromUtf8(valueOf(key, input));
|
return QString::fromUtf8(valueOf(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath CMakeConfigItem::filePathValueOf(const QByteArray &key, const QList<CMakeConfigItem> &input)
|
FilePath CMakeConfig::filePathValueOf(const QByteArray &key) const
|
||||||
{
|
{
|
||||||
return FilePath::fromUtf8(valueOf(key, input));
|
return FilePath::fromUtf8(valueOf(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CMakeConfigItem::expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key,
|
QString CMakeConfig::expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key) const
|
||||||
const QList<CMakeConfigItem> &input)
|
|
||||||
{
|
{
|
||||||
for (auto it = input.constBegin(); it != input.constEnd(); ++it) {
|
for (auto it = constBegin(); it != constEnd(); ++it) {
|
||||||
if (it->key == key)
|
if (it->key == key)
|
||||||
return it->expandedValue(k);
|
return it->expandedValue(k);
|
||||||
}
|
}
|
||||||
@@ -312,7 +311,7 @@ static CMakeConfigItem unsetItemFromString(const QString &input)
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<CMakeConfigItem> CMakeConfigItem::itemsFromArguments(const QStringList &list)
|
CMakeConfig CMakeConfig::fromArguments(const QStringList &list)
|
||||||
{
|
{
|
||||||
CMakeConfig result;
|
CMakeConfig result;
|
||||||
bool inSet = false;
|
bool inSet = false;
|
||||||
@@ -348,7 +347,7 @@ QList<CMakeConfigItem> CMakeConfigItem::itemsFromArguments(const QStringList &li
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<CMakeConfigItem> CMakeConfigItem::itemsFromFile(const Utils::FilePath &cacheFile, QString *errorMessage)
|
CMakeConfig CMakeConfig::fromFile(const Utils::FilePath &cacheFile, QString *errorMessage)
|
||||||
{
|
{
|
||||||
CMakeConfig result;
|
CMakeConfig result;
|
||||||
QFile cache(cacheFile.toString());
|
QFile cache(cacheFile.toString());
|
||||||
@@ -473,6 +472,11 @@ bool CMakeConfigItem::operator==(const CMakeConfigItem &o) const
|
|||||||
return o.key == key && o.value == value && o.isUnset == isUnset;
|
return o.key == key && o.value == value && o.isUnset == isUnset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint qHash(const CMakeConfigItem &it)
|
||||||
|
{
|
||||||
|
return ::qHash(it.key) ^ ::qHash(it.value) ^ ::qHash(it.isUnset);
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_TESTS
|
#if WITH_TESTS
|
||||||
|
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
@@ -43,18 +43,14 @@ class Kit;
|
|||||||
|
|
||||||
namespace CMakeProjectManager {
|
namespace CMakeProjectManager {
|
||||||
|
|
||||||
class CMAKE_EXPORT CMakeConfigItem {
|
class CMAKE_EXPORT CMakeConfigItem
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC, UNINITIALIZED };
|
enum Type { FILEPATH, PATH, BOOL, STRING, INTERNAL, STATIC, UNINITIALIZED };
|
||||||
CMakeConfigItem();
|
CMakeConfigItem();
|
||||||
CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v, const QStringList &s = {});
|
CMakeConfigItem(const QByteArray &k, Type t, const QByteArray &d, const QByteArray &v, const QStringList &s = {});
|
||||||
CMakeConfigItem(const QByteArray &k, const QByteArray &v);
|
CMakeConfigItem(const QByteArray &k, const QByteArray &v);
|
||||||
|
|
||||||
static QByteArray valueOf(const QByteArray &key, const QList<CMakeConfigItem> &input);
|
|
||||||
static QString stringValueOf(const QByteArray &key, const QList<CMakeConfigItem> &input);
|
|
||||||
static Utils::FilePath filePathValueOf(const QByteArray &key, const QList<CMakeConfigItem> &input);
|
|
||||||
static QString expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key,
|
|
||||||
const QList<CMakeConfigItem> &input);
|
|
||||||
static QStringList cmakeSplitValue(const QString &in, bool keepEmpty = false);
|
static QStringList cmakeSplitValue(const QString &in, bool keepEmpty = false);
|
||||||
static Type typeStringToType(const QByteArray &typeString);
|
static Type typeStringToType(const QByteArray &typeString);
|
||||||
static QString typeToTypeString(const Type t);
|
static QString typeToTypeString(const Type t);
|
||||||
@@ -66,8 +62,6 @@ public:
|
|||||||
|
|
||||||
static bool less(const CMakeConfigItem &a, const CMakeConfigItem &b);
|
static bool less(const CMakeConfigItem &a, const CMakeConfigItem &b);
|
||||||
static CMakeConfigItem fromString(const QString &s);
|
static CMakeConfigItem fromString(const QString &s);
|
||||||
static QList<CMakeConfigItem> itemsFromArguments(const QStringList &list);
|
|
||||||
static QList<CMakeConfigItem> itemsFromFile(const Utils::FilePath &input, QString *errorMessage);
|
|
||||||
QString toString(const Utils::MacroExpander *expander = nullptr) const;
|
QString toString(const Utils::MacroExpander *expander = nullptr) const;
|
||||||
QString toArgument(const Utils::MacroExpander *expander = nullptr) const;
|
QString toArgument(const Utils::MacroExpander *expander = nullptr) const;
|
||||||
QString toCMakeSetLine(const Utils::MacroExpander *expander = nullptr) const;
|
QString toCMakeSetLine(const Utils::MacroExpander *expander = nullptr) const;
|
||||||
@@ -83,6 +77,25 @@ public:
|
|||||||
QByteArray documentation;
|
QByteArray documentation;
|
||||||
QStringList values;
|
QStringList values;
|
||||||
};
|
};
|
||||||
using CMakeConfig = QList<CMakeConfigItem>;
|
|
||||||
|
uint qHash(const CMakeConfigItem &it); // needed for MSVC
|
||||||
|
|
||||||
|
class CMAKE_EXPORT CMakeConfig : public QList<CMakeConfigItem>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CMakeConfig() = default;
|
||||||
|
CMakeConfig(const QList<CMakeConfigItem> &items) : QList<CMakeConfigItem>(items) {}
|
||||||
|
CMakeConfig(std::initializer_list<CMakeConfigItem> items) : QList<CMakeConfigItem>(items) {}
|
||||||
|
|
||||||
|
const QList<CMakeConfigItem> &toList() const { return *this; }
|
||||||
|
|
||||||
|
static CMakeConfig fromArguments(const QStringList &list);
|
||||||
|
static CMakeConfig fromFile(const Utils::FilePath &input, QString *errorMessage);
|
||||||
|
|
||||||
|
QByteArray valueOf(const QByteArray &key) const;
|
||||||
|
QString stringValueOf(const QByteArray &key) const;
|
||||||
|
Utils::FilePath filePathValueOf(const QByteArray &key) const;
|
||||||
|
QString expandedValueOf(const ProjectExplorer::Kit *k, const QByteArray &key) const;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace CMakeProjectManager
|
} // namespace CMakeProjectManager
|
||||||
|
@@ -996,14 +996,14 @@ void CMakeConfigurationKitAspect::setConfiguration(Kit *k, const CMakeConfig &co
|
|||||||
{
|
{
|
||||||
if (!k)
|
if (!k)
|
||||||
return;
|
return;
|
||||||
const QStringList tmp = Utils::transform(config, [](const CMakeConfigItem &i) { return i.toString(); });
|
const QStringList tmp = Utils::transform(config.toList(),
|
||||||
|
[](const CMakeConfigItem &i) { return i.toString(); });
|
||||||
k->setValue(CONFIGURATION_ID, tmp);
|
k->setValue(CONFIGURATION_ID, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CMakeConfigurationKitAspect::toStringList(const Kit *k)
|
QStringList CMakeConfigurationKitAspect::toStringList(const Kit *k)
|
||||||
{
|
{
|
||||||
QStringList current
|
QStringList current = Utils::transform(CMakeConfigurationKitAspect::configuration(k).toList(),
|
||||||
= Utils::transform(CMakeConfigurationKitAspect::configuration(k),
|
|
||||||
[](const CMakeConfigItem &i) { return i.toString(); });
|
[](const CMakeConfigItem &i) { return i.toString(); });
|
||||||
current = Utils::filtered(current, [](const QString &s) { return !s.isEmpty(); });
|
current = Utils::filtered(current, [](const QString &s) { return !s.isEmpty(); });
|
||||||
Utils::sort(current);
|
Utils::sort(current);
|
||||||
@@ -1023,7 +1023,7 @@ void CMakeConfigurationKitAspect::fromStringList(Kit *k, const QStringList &in)
|
|||||||
|
|
||||||
QStringList CMakeConfigurationKitAspect::toArgumentsList(const Kit *k)
|
QStringList CMakeConfigurationKitAspect::toArgumentsList(const Kit *k)
|
||||||
{
|
{
|
||||||
return Utils::transform(CMakeConfigurationKitAspect::configuration(k),
|
return Utils::transform(CMakeConfigurationKitAspect::configuration(k).toList(),
|
||||||
[](const CMakeConfigItem &i) { return i.toArgument(nullptr); });
|
[](const CMakeConfigItem &i) { return i.toArgument(nullptr); });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,8 +1046,8 @@ QVariant CMakeConfigurationKitAspect::defaultValue(const Kit *k) const
|
|||||||
{
|
{
|
||||||
// FIXME: Convert preload scripts
|
// FIXME: Convert preload scripts
|
||||||
CMakeConfig config = defaultConfiguration(k);
|
CMakeConfig config = defaultConfiguration(k);
|
||||||
const QStringList tmp
|
const QStringList tmp = Utils::transform(config.toList(),
|
||||||
= Utils::transform(config, [](const CMakeConfigItem &i) { return i.toString(); });
|
[](const CMakeConfigItem &i) { return i.toString(); });
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -135,20 +135,16 @@ QStringList CMakeProjectImporter::importCandidates()
|
|||||||
static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
|
static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
|
||||||
{
|
{
|
||||||
// Qt4 way to define things (more convenient for us, so try this first;-)
|
// Qt4 way to define things (more convenient for us, so try this first;-)
|
||||||
FilePath qmake
|
const FilePath qmake = config.filePathValueOf("QT_QMAKE_EXECUTABLE");
|
||||||
= FilePath::fromUtf8(CMakeConfigItem::valueOf(QByteArray("QT_QMAKE_EXECUTABLE"), config));
|
|
||||||
qCDebug(cmInputLog) << "QT_QMAKE_EXECUTABLE=" << qmake.toUserOutput();
|
qCDebug(cmInputLog) << "QT_QMAKE_EXECUTABLE=" << qmake.toUserOutput();
|
||||||
if (!qmake.isEmpty())
|
if (!qmake.isEmpty())
|
||||||
return qmake;
|
return qmake;
|
||||||
|
|
||||||
// Check Qt5 settings: oh, the horror!
|
// Check Qt5 settings: oh, the horror!
|
||||||
const FilePath qtCMakeDir = [config] {
|
const FilePath qtCMakeDir = [config] {
|
||||||
FilePath tmp = FilePath::fromUtf8(
|
FilePath tmp = config.filePathValueOf("Qt5Core_DIR");
|
||||||
CMakeConfigItem::valueOf(QByteArray("Qt5Core_DIR"), config));
|
if (tmp.isEmpty())
|
||||||
if (tmp.isEmpty()) {
|
tmp = config.filePathValueOf("Qt6Core_DIR");
|
||||||
tmp = FilePath::fromUtf8(
|
|
||||||
CMakeConfigItem::valueOf(QByteArray("Qt6Core_DIR"), config));
|
|
||||||
}
|
|
||||||
return tmp;
|
return tmp;
|
||||||
}();
|
}();
|
||||||
qCDebug(cmInputLog) << "QtXCore_DIR=" << qtCMakeDir.toUserOutput();
|
qCDebug(cmInputLog) << "QtXCore_DIR=" << qtCMakeDir.toUserOutput();
|
||||||
@@ -206,11 +202,11 @@ static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
|
|||||||
cmake.setEnvironment(env);
|
cmake.setEnvironment(env);
|
||||||
cmake.setTimeOutMessageBoxEnabled(false);
|
cmake.setTimeOutMessageBoxEnabled(false);
|
||||||
|
|
||||||
QString cmakeGenerator = CMakeConfigItem::stringValueOf(QByteArray("CMAKE_GENERATOR"), config);
|
QString cmakeGenerator = config.stringValueOf(QByteArray("CMAKE_GENERATOR"));
|
||||||
FilePath cmakeExecutable = CMakeConfigItem::filePathValueOf(QByteArray("CMAKE_COMMAND"), config);
|
FilePath cmakeExecutable = config.filePathValueOf(QByteArray("CMAKE_COMMAND"));
|
||||||
FilePath cmakeMakeProgram =CMakeConfigItem::filePathValueOf(QByteArray("CMAKE_MAKE_PROGRAM"), config);
|
FilePath cmakeMakeProgram = config.filePathValueOf(QByteArray("CMAKE_MAKE_PROGRAM"));
|
||||||
FilePath toolchainFile = CMakeConfigItem::filePathValueOf(QByteArray("CMAKE_TOOLCHAIN_FILE"), config);
|
FilePath toolchainFile = config.filePathValueOf(QByteArray("CMAKE_TOOLCHAIN_FILE"));
|
||||||
FilePath hostPath = CMakeConfigItem::filePathValueOf(QByteArray("QT_HOST_PATH"), config);
|
FilePath hostPath = config.filePathValueOf(QByteArray("QT_HOST_PATH"));
|
||||||
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
args.push_back("-S");
|
args.push_back("-S");
|
||||||
@@ -270,7 +266,7 @@ static QVector<ToolChainDescription> extractToolChainsFromCache(const CMakeConfi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!haveCCxxCompiler) {
|
if (!haveCCxxCompiler) {
|
||||||
const QByteArray generator = CMakeConfigItem::valueOf(QByteArray("CMAKE_GENERATOR"), config);
|
const QByteArray generator = config.valueOf("CMAKE_GENERATOR");
|
||||||
QString cCompilerName;
|
QString cCompilerName;
|
||||||
QString cxxCompilerName;
|
QString cxxCompilerName;
|
||||||
if (generator.contains("Visual Studio")) {
|
if (generator.contains("Visual Studio")) {
|
||||||
@@ -282,8 +278,7 @@ static QVector<ToolChainDescription> extractToolChainsFromCache(const CMakeConfi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cCompilerName.isEmpty() && !cxxCompilerName.isEmpty()) {
|
if (!cCompilerName.isEmpty() && !cxxCompilerName.isEmpty()) {
|
||||||
const FilePath linker = FilePath::fromUtf8(
|
const FilePath linker = config.filePathValueOf("CMAKE_LINKER");
|
||||||
CMakeConfigItem::valueOf(QByteArray("CMAKE_LINKER"), config));
|
|
||||||
if (!linker.isEmpty()) {
|
if (!linker.isEmpty()) {
|
||||||
const FilePath compilerPath = linker.parentDir();
|
const FilePath compilerPath = linker.parentDir();
|
||||||
result.append({compilerPath.pathAppended(cCompilerName),
|
result.append({compilerPath.pathAppended(cCompilerName),
|
||||||
@@ -315,21 +310,19 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArrayList buildConfigurationTypes = {CMakeConfigItem::valueOf("CMAKE_BUILD_TYPE", config)};
|
QByteArrayList buildConfigurationTypes = {config.valueOf("CMAKE_BUILD_TYPE")};
|
||||||
if (buildConfigurationTypes.front().isEmpty()) {
|
if (buildConfigurationTypes.front().isEmpty()) {
|
||||||
QByteArray buildConfigurationTypesString =
|
QByteArray buildConfigurationTypesString = config.valueOf("CMAKE_CONFIGURATION_TYPES");
|
||||||
CMakeConfigItem::valueOf("CMAKE_CONFIGURATION_TYPES", config);
|
if (!buildConfigurationTypesString.isEmpty())
|
||||||
if (!buildConfigurationTypesString.isEmpty()) {
|
|
||||||
buildConfigurationTypes = buildConfigurationTypesString.split(';');
|
buildConfigurationTypes = buildConfigurationTypesString.split(';');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
QList<void *> result;
|
QList<void *> result;
|
||||||
for (auto const &buildType: qAsConst(buildConfigurationTypes)) {
|
for (auto const &buildType: qAsConst(buildConfigurationTypes)) {
|
||||||
auto data = std::make_unique<DirectoryData>();
|
auto data = std::make_unique<DirectoryData>();
|
||||||
|
|
||||||
data->cmakeHomeDirectory =
|
data->cmakeHomeDirectory =
|
||||||
FilePath::fromUserInput(CMakeConfigItem::stringValueOf("CMAKE_HOME_DIRECTORY", config))
|
FilePath::fromUserInput(config.stringValueOf("CMAKE_HOME_DIRECTORY"))
|
||||||
.canonicalPath();
|
.canonicalPath();
|
||||||
const FilePath canonicalProjectDirectory = projectDirectory().canonicalPath();
|
const FilePath canonicalProjectDirectory = projectDirectory().canonicalPath();
|
||||||
if (data->cmakeHomeDirectory != canonicalProjectDirectory) {
|
if (data->cmakeHomeDirectory != canonicalProjectDirectory) {
|
||||||
@@ -344,12 +337,12 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
data->buildDirectory = importPath;
|
data->buildDirectory = importPath;
|
||||||
data->cmakeBuildType = buildType;
|
data->cmakeBuildType = buildType;
|
||||||
|
|
||||||
data->cmakeBinary = CMakeConfigItem::filePathValueOf("CMAKE_COMMAND", config);
|
data->cmakeBinary = config.filePathValueOf("CMAKE_COMMAND");
|
||||||
data->generator = CMakeConfigItem::stringValueOf("CMAKE_GENERATOR", config);
|
data->generator = config.stringValueOf("CMAKE_GENERATOR");
|
||||||
data->extraGenerator = CMakeConfigItem::stringValueOf("CMAKE_EXTRA_GENERATOR", config);
|
data->extraGenerator = config.stringValueOf("CMAKE_EXTRA_GENERATOR");
|
||||||
data->platform = CMakeConfigItem::stringValueOf("CMAKE_GENERATOR_PLATFORM", config);
|
data->platform = config.stringValueOf("CMAKE_GENERATOR_PLATFORM");
|
||||||
data->toolset = CMakeConfigItem::stringValueOf("CMAKE_GENERATOR_TOOLSET", config);
|
data->toolset = config.stringValueOf("CMAKE_GENERATOR_TOOLSET");
|
||||||
data->sysroot = CMakeConfigItem::filePathValueOf("CMAKE_SYSROOT", config);
|
data->sysroot = config.filePathValueOf("CMAKE_SYSROOT");
|
||||||
|
|
||||||
// Qt:
|
// Qt:
|
||||||
const FilePath qmake = qmakeFromCMakeCache(config);
|
const FilePath qmake = qmakeFromCMakeCache(config);
|
||||||
|
@@ -203,7 +203,7 @@ QList<ConfigModel::DataItem> ConfigModel::configurationForCMake() const
|
|||||||
|
|
||||||
void ConfigModel::setConfiguration(const CMakeConfig &config)
|
void ConfigModel::setConfiguration(const CMakeConfig &config)
|
||||||
{
|
{
|
||||||
setConfiguration(Utils::transform(config, [](const CMakeConfigItem &i) {
|
setConfiguration(Utils::transform(config.toList(), [](const CMakeConfigItem &i) {
|
||||||
return DataItem(i);
|
return DataItem(i);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@@ -337,7 +337,7 @@ void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &conf
|
|||||||
QByteArray contents;
|
QByteArray contents;
|
||||||
contents.append("# This file is managed by Qt Creator, do not edit!\n\n");
|
contents.append("# This file is managed by Qt Creator, do not edit!\n\n");
|
||||||
contents.append(
|
contents.append(
|
||||||
transform(CMakeConfigItem::itemsFromArguments(configurationArguments),
|
transform(CMakeConfig::fromArguments(configurationArguments).toList(),
|
||||||
[](const CMakeConfigItem &item) {
|
[](const CMakeConfigItem &item) {
|
||||||
return item.toCMakeSetLine(nullptr);
|
return item.toCMakeSetLine(nullptr);
|
||||||
})
|
})
|
||||||
|
@@ -69,6 +69,8 @@
|
|||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QTextBrowser>
|
#include <QTextBrowser>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
@@ -304,9 +306,11 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
~DockerDevicePrivate() { delete m_shell; }
|
~DockerDevicePrivate() { stopCurrentContainer(); }
|
||||||
|
|
||||||
bool runInContainer(const CommandLine &cmd) const;
|
bool runInContainer(const CommandLine &cmd) const;
|
||||||
|
bool runInShell(const CommandLine &cmd) const;
|
||||||
|
QString outputForRunInShell(const CommandLine &cmd) const;
|
||||||
|
|
||||||
void tryCreateLocalFileAccess();
|
void tryCreateLocalFileAccess();
|
||||||
|
|
||||||
@@ -318,6 +322,7 @@ public:
|
|||||||
|
|
||||||
// For local file access
|
// For local file access
|
||||||
QPointer<QtcProcess> m_shell;
|
QPointer<QtcProcess> m_shell;
|
||||||
|
mutable QMutex m_shellMutex;
|
||||||
QString m_container;
|
QString m_container;
|
||||||
QString m_mergedDir;
|
QString m_mergedDir;
|
||||||
QFileSystemWatcher m_mergedDirWatcher;
|
QFileSystemWatcher m_mergedDirWatcher;
|
||||||
@@ -359,12 +364,15 @@ public:
|
|||||||
auto daemonStateLabel = new QLabel(tr("Daemon state:"));
|
auto daemonStateLabel = new QLabel(tr("Daemon state:"));
|
||||||
m_daemonReset = new QToolButton;
|
m_daemonReset = new QToolButton;
|
||||||
m_daemonReset->setIcon(Icons::INFO.icon());
|
m_daemonReset->setIcon(Icons::INFO.icon());
|
||||||
m_daemonReset->setToolTip(tr("Daemon state not evaluated."));
|
m_daemonReset->setToolTip(tr("Clear detected daemon state. "
|
||||||
|
"It will be automatically re-evaluated next time an access is needed."));
|
||||||
|
|
||||||
|
m_daemonState = new QLabel(tr("Daemon state not evaluated."));
|
||||||
|
|
||||||
connect(m_daemonReset, &QToolButton::clicked, this, [this, dockerDevice] {
|
connect(m_daemonReset, &QToolButton::clicked, this, [this, dockerDevice] {
|
||||||
dockerDevice->resetDaemonState();
|
dockerDevice->resetDaemonState();
|
||||||
m_daemonReset->setIcon(Icons::INFO.icon());
|
m_daemonReset->setIcon(Icons::INFO.icon());
|
||||||
m_daemonReset->setToolTip(tr("Daemon state not evaluated."));
|
m_daemonState->setText(tr("Daemon state not evaluated."));
|
||||||
});
|
});
|
||||||
|
|
||||||
m_runAsOutsideUser = new QCheckBox(tr("Run as outside user"));
|
m_runAsOutsideUser = new QCheckBox(tr("Run as outside user"));
|
||||||
@@ -403,10 +411,11 @@ public:
|
|||||||
|
|
||||||
if (!dockerDevice->isDaemonRunning()) {
|
if (!dockerDevice->isDaemonRunning()) {
|
||||||
logView->append(tr("Docker daemon appears to be not running."));
|
logView->append(tr("Docker daemon appears to be not running."));
|
||||||
m_daemonReset->setToolTip(tr("Daemon not running. Push to reset the state."));
|
m_daemonState->setText(tr("Docker daemon not running."));
|
||||||
m_daemonReset->setIcon(Icons::CRITICAL.icon());
|
m_daemonReset->setIcon(Icons::CRITICAL.icon());
|
||||||
} else {
|
} else {
|
||||||
m_daemonReset->setToolTip(tr("Docker daemon running."));
|
logView->append(tr("Docker daemon appears to be running."));
|
||||||
|
m_daemonState->setText(tr("Docker daemon running."));
|
||||||
m_daemonReset->setIcon(Icons::OK.icon());
|
m_daemonReset->setIcon(Icons::OK.icon());
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -427,7 +436,7 @@ public:
|
|||||||
Form {
|
Form {
|
||||||
idLabel, m_idLineEdit, Break(),
|
idLabel, m_idLineEdit, Break(),
|
||||||
repoLabel, m_repoLineEdit, Break(),
|
repoLabel, m_repoLineEdit, Break(),
|
||||||
daemonStateLabel, m_daemonReset, Break(),
|
daemonStateLabel, m_daemonReset, m_daemonState, Break(),
|
||||||
m_runAsOutsideUser, Break(),
|
m_runAsOutsideUser, Break(),
|
||||||
tr("Paths to mount:"), m_pathsLineEdit, Break(),
|
tr("Paths to mount:"), m_pathsLineEdit, Break(),
|
||||||
Column {
|
Column {
|
||||||
@@ -445,6 +454,7 @@ private:
|
|||||||
QLineEdit *m_idLineEdit;
|
QLineEdit *m_idLineEdit;
|
||||||
QLineEdit *m_repoLineEdit;
|
QLineEdit *m_repoLineEdit;
|
||||||
QToolButton *m_daemonReset;
|
QToolButton *m_daemonReset;
|
||||||
|
QLabel *m_daemonState;
|
||||||
QCheckBox *m_runAsOutsideUser;
|
QCheckBox *m_runAsOutsideUser;
|
||||||
QLineEdit *m_pathsLineEdit;
|
QLineEdit *m_pathsLineEdit;
|
||||||
|
|
||||||
@@ -745,6 +755,20 @@ void DockerDevicePrivate::stopCurrentContainer()
|
|||||||
if (m_container.isEmpty() || m_accessible == NoDaemon)
|
if (m_container.isEmpty() || m_accessible == NoDaemon)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_shell) {
|
||||||
|
QMutexLocker l(&m_shellMutex);
|
||||||
|
m_shell->write("exit\n");
|
||||||
|
m_shell->waitForFinished(2000);
|
||||||
|
if (m_shell->state() == QProcess::NotRunning) {
|
||||||
|
LOG("Clean exit via shell");
|
||||||
|
m_container.clear();
|
||||||
|
m_mergedDir.clear();
|
||||||
|
delete m_shell;
|
||||||
|
m_shell = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QtcProcess proc;
|
QtcProcess proc;
|
||||||
proc.setCommand({"docker", {"container", "stop", m_container}});
|
proc.setCommand({"docker", {"container", "stop", m_container}});
|
||||||
|
|
||||||
@@ -1019,7 +1043,7 @@ bool DockerDevice::isExecutableFile(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-x", path}});
|
return d->runInShell({"test", {"-x", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::isReadableFile(const FilePath &filePath) const
|
bool DockerDevice::isReadableFile(const FilePath &filePath) const
|
||||||
@@ -1033,7 +1057,7 @@ bool DockerDevice::isReadableFile(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-r", path, "-a", "-f", path}});
|
return d->runInShell({"test", {"-r", path, "-a", "-f", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::isWritableFile(const Utils::FilePath &filePath) const
|
bool DockerDevice::isWritableFile(const Utils::FilePath &filePath) const
|
||||||
@@ -1047,7 +1071,7 @@ bool DockerDevice::isWritableFile(const Utils::FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-w", path, "-a", "-f", path}});
|
return d->runInShell({"test", {"-w", path, "-a", "-f", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::isReadableDirectory(const FilePath &filePath) const
|
bool DockerDevice::isReadableDirectory(const FilePath &filePath) const
|
||||||
@@ -1061,7 +1085,7 @@ bool DockerDevice::isReadableDirectory(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-r", path, "-a", "-d", path}});
|
return d->runInShell({"test", {"-r", path, "-a", "-d", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::isWritableDirectory(const FilePath &filePath) const
|
bool DockerDevice::isWritableDirectory(const FilePath &filePath) const
|
||||||
@@ -1075,7 +1099,7 @@ bool DockerDevice::isWritableDirectory(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-w", path, "-a", "-d", path}});
|
return d->runInShell({"test", {"-w", path, "-a", "-d", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::isFile(const FilePath &filePath) const
|
bool DockerDevice::isFile(const FilePath &filePath) const
|
||||||
@@ -1089,7 +1113,7 @@ bool DockerDevice::isFile(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-f", path}});
|
return d->runInShell({"test", {"-f", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::isDirectory(const FilePath &filePath) const
|
bool DockerDevice::isDirectory(const FilePath &filePath) const
|
||||||
@@ -1103,7 +1127,7 @@ bool DockerDevice::isDirectory(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-d", path}});
|
return d->runInShell({"test", {"-d", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::createDirectory(const FilePath &filePath) const
|
bool DockerDevice::createDirectory(const FilePath &filePath) const
|
||||||
@@ -1131,7 +1155,7 @@ bool DockerDevice::exists(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"test", {"-e", path}});
|
return d->runInShell({"test", {"-e", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::ensureExistingFile(const FilePath &filePath) const
|
bool DockerDevice::ensureExistingFile(const FilePath &filePath) const
|
||||||
@@ -1145,7 +1169,7 @@ bool DockerDevice::ensureExistingFile(const FilePath &filePath) const
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
const QString path = filePath.path();
|
const QString path = filePath.path();
|
||||||
return d->runInContainer({"touch", {path}});
|
return d->runInShell({"touch", {path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::removeFile(const FilePath &filePath) const
|
bool DockerDevice::removeFile(const FilePath &filePath) const
|
||||||
@@ -1172,9 +1196,15 @@ bool DockerDevice::removeRecursively(const FilePath &filePath) const
|
|||||||
LOG("Remove recursively? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
|
LOG("Remove recursively? " << filePath.toUserOutput() << localAccess.toUserOutput() << res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
// Open this up only when really needed.
|
|
||||||
// return d->runInContainer({"rm", "-rf", {filePath.path()}});
|
const QString path = filePath.cleanPath().path();
|
||||||
return false;
|
// We are expecting this only to be called in a context of build directories or similar.
|
||||||
|
// Chicken out in some cases that _might_ be user code errors.
|
||||||
|
QTC_ASSERT(path.startsWith('/'), return false);
|
||||||
|
const int levelsNeeded = path.startsWith("/home/") ? 4 : 3;
|
||||||
|
QTC_ASSERT(path.count('/') >= levelsNeeded, return false);
|
||||||
|
|
||||||
|
return d->runInContainer({"rm", {"-rf", "--", path}});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::copyFile(const FilePath &filePath, const FilePath &target) const
|
bool DockerDevice::copyFile(const FilePath &filePath, const FilePath &target) const
|
||||||
@@ -1240,8 +1270,44 @@ FilePath DockerDevice::symLinkTarget(const FilePath &filePath) const
|
|||||||
return {};
|
return {};
|
||||||
return mapToGlobalPath(target);
|
return mapToGlobalPath(target);
|
||||||
}
|
}
|
||||||
QTC_CHECK(false);
|
|
||||||
return {};
|
const QString output = d->outputForRunInShell({"readlink", {"-n", "-e", filePath.path()}});
|
||||||
|
return output.isEmpty() ? FilePath() : filePath.withNewPath(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FilePaths filterEntriesHelper(const FilePath &base,
|
||||||
|
const QStringList &entries,
|
||||||
|
const QStringList &nameFilters,
|
||||||
|
QDir::Filters filters,
|
||||||
|
QDir::SortFlags sort)
|
||||||
|
{
|
||||||
|
const QList<QRegularExpression> nameRegexps = transform(nameFilters, [](const QString &filter) {
|
||||||
|
QRegularExpression re;
|
||||||
|
re.setPattern(QRegularExpression::wildcardToRegularExpression(filter));
|
||||||
|
QTC_CHECK(re.isValid());
|
||||||
|
return re;
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto nameMatches = [&nameRegexps](const QString &fileName) {
|
||||||
|
for (const QRegularExpression &re : nameRegexps) {
|
||||||
|
const QRegularExpressionMatch match = re.match(fileName);
|
||||||
|
if (match.hasMatch())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: Handle sort and filters. For now bark on unsupported options.
|
||||||
|
QTC_CHECK(filters == QDir::NoFilter);
|
||||||
|
QTC_CHECK(sort == QDir::NoSort);
|
||||||
|
|
||||||
|
FilePaths result;
|
||||||
|
for (const QString &entry : entries) {
|
||||||
|
if (!nameMatches(entry))
|
||||||
|
continue;
|
||||||
|
result.append(base.pathAppended(entry));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePaths DockerDevice::directoryEntries(const FilePath &filePath,
|
FilePaths DockerDevice::directoryEntries(const FilePath &filePath,
|
||||||
@@ -1258,13 +1324,9 @@ FilePaths DockerDevice::directoryEntries(const FilePath &filePath,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
QtcProcess proc;
|
const QString output = d->outputForRunInShell({"ls", {"-1", "-b", "--", filePath.path()}});
|
||||||
proc.setCommand({"ls", {"-1", "-b", "--", filePath.path()}});
|
QStringList entries = output.split('\n', Qt::SkipEmptyParts);
|
||||||
runProcess(proc);
|
return filterEntriesHelper(filePath, entries, nameFilters, filters, sort);
|
||||||
proc.waitForFinished();
|
|
||||||
|
|
||||||
QStringList entries = proc.stdOut().split('\n', Qt::SkipEmptyParts);
|
|
||||||
return FilePath::filterEntriesHelper(filePath, entries, nameFilters, filters, sort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const
|
QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qint64 offset) const
|
||||||
@@ -1291,15 +1353,35 @@ QByteArray DockerDevice::fileContents(const FilePath &filePath, qint64 limit, qi
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::writeFileContents(const Utils::FilePath &filePath, const QByteArray &data) const
|
bool DockerDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(handlesFile(filePath), return {});
|
QTC_ASSERT(handlesFile(filePath), return {});
|
||||||
tryCreateLocalFileAccess();
|
tryCreateLocalFileAccess();
|
||||||
if (hasLocalFileAccess())
|
if (hasLocalFileAccess())
|
||||||
return mapToLocalAccess(filePath).writeFileContents(data);
|
return mapToLocalAccess(filePath).writeFileContents(data);
|
||||||
|
|
||||||
QTC_CHECK(false); // FIXME: Implement
|
// This following would be the generic Unix solution.
|
||||||
return {};
|
// But it doesn't pass input. FIXME: Why?
|
||||||
|
// QtcProcess proc;
|
||||||
|
// proc.setCommand({"dd", {"of=" + filePath.path()}});
|
||||||
|
// proc.setWriteData(data);
|
||||||
|
// runProcess(proc);
|
||||||
|
// proc.waitForFinished();
|
||||||
|
|
||||||
|
TemporaryFile tempFile("dockertransport-XXXXXX");
|
||||||
|
tempFile.open();
|
||||||
|
tempFile.write(data);
|
||||||
|
|
||||||
|
const QString tempName = tempFile.fileName();
|
||||||
|
tempFile.close();
|
||||||
|
|
||||||
|
CommandLine cmd{"docker", {"cp", tempName, d->m_container + ':' + filePath.path()}};
|
||||||
|
|
||||||
|
QtcProcess proc;
|
||||||
|
proc.setCommand(cmd);
|
||||||
|
proc.runBlocking();
|
||||||
|
|
||||||
|
return proc.exitCode() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::runProcess(QtcProcess &process) const
|
void DockerDevice::runProcess(QtcProcess &process) const
|
||||||
@@ -1375,6 +1457,48 @@ bool DockerDevicePrivate::runInContainer(const CommandLine &cmd) const
|
|||||||
return exitCode == 0;
|
return exitCode == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockerDevicePrivate::runInShell(const CommandLine &cmd) const
|
||||||
|
{
|
||||||
|
if (m_accessible == NoDaemon)
|
||||||
|
return false;
|
||||||
|
QTC_ASSERT(m_shell, return false);
|
||||||
|
QMutexLocker l(&m_shellMutex);
|
||||||
|
m_shell->readAllStandardOutput(); // clean possible left-overs
|
||||||
|
m_shell->write(cmd.toUserOutput().toUtf8() + "\necho $?\n");
|
||||||
|
m_shell->waitForReadyRead();
|
||||||
|
QByteArray output = m_shell->readAllStandardOutput();
|
||||||
|
int result = output.toInt();
|
||||||
|
LOG("Run command in shell:" << cmd.toUserOutput() << "result: " << output << " ==>" << result);
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate hex value
|
||||||
|
static QByteArray randomHex()
|
||||||
|
{
|
||||||
|
quint32 val = QRandomGenerator::global()->generate();
|
||||||
|
return QString::number(val, 16).toUtf8();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) const
|
||||||
|
{
|
||||||
|
if (m_accessible == NoDaemon)
|
||||||
|
return {};
|
||||||
|
QTC_ASSERT(m_shell, return {});
|
||||||
|
QMutexLocker l(&m_shellMutex);
|
||||||
|
m_shell->readAllStandardOutput(); // clean possible left-overs
|
||||||
|
const QByteArray markerWithNewLine("___QC_DOCKER_" + randomHex() + "_OUTPUT_MARKER___\n");
|
||||||
|
m_shell->write(cmd.toUserOutput().toUtf8() + "\necho -n \"" + markerWithNewLine + "\"\n");
|
||||||
|
QByteArray output;
|
||||||
|
while (!output.endsWith(markerWithNewLine)) {
|
||||||
|
m_shell->waitForReadyRead();
|
||||||
|
output.append(m_shell->readAllStandardOutput());
|
||||||
|
}
|
||||||
|
LOG("Run command in shell:" << cmd.toUserOutput() << "output size:" << output.size());
|
||||||
|
if (QTC_GUARD(output.endsWith(markerWithNewLine)))
|
||||||
|
output.chop(markerWithNewLine.size());
|
||||||
|
return QString::fromUtf8(output);
|
||||||
|
}
|
||||||
|
|
||||||
// Factory
|
// Factory
|
||||||
|
|
||||||
DockerDeviceFactory::DockerDeviceFactory()
|
DockerDeviceFactory::DockerDeviceFactory()
|
||||||
|
@@ -525,7 +525,7 @@ DeviceManager::DeviceManager(bool isInstance) : d(std::make_unique<DeviceManager
|
|||||||
return device->systemEnvironment();
|
return device->systemEnvironment();
|
||||||
};
|
};
|
||||||
|
|
||||||
FilePath::setDeviceFileHooks(deviceHooks);
|
FileUtils::setDeviceFileHooks(deviceHooks);
|
||||||
|
|
||||||
DeviceProcessHooks processHooks;
|
DeviceProcessHooks processHooks;
|
||||||
|
|
||||||
|
@@ -347,7 +347,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
|
|||||||
importSection = importHash[entry.requiredImport()];
|
importSection = importHash[entry.requiredImport()];
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (catName == "My Quick3D Components") {
|
} else if (catName == ItemLibraryImport::quick3DAssetsTitle()) {
|
||||||
importSection = importHash[ItemLibraryImport::quick3DAssetsTitle()];
|
importSection = importHash[ItemLibraryImport::quick3DAssetsTitle()];
|
||||||
} else {
|
} else {
|
||||||
if (catName.startsWith("Qt Quick - "))
|
if (catName.startsWith("Qt Quick - "))
|
||||||
|
@@ -79,6 +79,7 @@ extend_qtc_executable(sdktool
|
|||||||
DEFINES QTCREATOR_UTILS_STATIC_LIB
|
DEFINES QTCREATOR_UTILS_STATIC_LIB
|
||||||
SOURCES
|
SOURCES
|
||||||
environment.cpp environment.h
|
environment.cpp environment.h
|
||||||
|
filepath.cpp filepath.h
|
||||||
fileutils.cpp fileutils.h
|
fileutils.cpp fileutils.h
|
||||||
hostosinfo.cpp hostosinfo.h
|
hostosinfo.cpp hostosinfo.h
|
||||||
namevaluedictionary.cpp namevaluedictionary.h
|
namevaluedictionary.cpp namevaluedictionary.h
|
||||||
|
@@ -32,6 +32,7 @@ SOURCES += \
|
|||||||
rmtoolchainoperation.cpp \
|
rmtoolchainoperation.cpp \
|
||||||
settings.cpp \
|
settings.cpp \
|
||||||
$$UTILS/environment.cpp \
|
$$UTILS/environment.cpp \
|
||||||
|
$$UTILS/filepath.cpp \
|
||||||
$$UTILS/fileutils.cpp \
|
$$UTILS/fileutils.cpp \
|
||||||
$$UTILS/hostosinfo.cpp \
|
$$UTILS/hostosinfo.cpp \
|
||||||
$$UTILS/namevaluedictionary.cpp \
|
$$UTILS/namevaluedictionary.cpp \
|
||||||
@@ -65,6 +66,7 @@ HEADERS += \
|
|||||||
rmtoolchainoperation.h \
|
rmtoolchainoperation.h \
|
||||||
settings.h \
|
settings.h \
|
||||||
$$UTILS/environment.h \
|
$$UTILS/environment.h \
|
||||||
|
$$UTILS/filepath.h \
|
||||||
$$UTILS/fileutils.h \
|
$$UTILS/fileutils.h \
|
||||||
$$UTILS/hostosinfo.h \
|
$$UTILS/hostosinfo.h \
|
||||||
$$UTILS/namevaluedictionary.h \
|
$$UTILS/namevaluedictionary.h \
|
||||||
|
@@ -70,6 +70,7 @@ QtcTool {
|
|||||||
files: [
|
files: [
|
||||||
"commandline.cpp", "commandline.h",
|
"commandline.cpp", "commandline.h",
|
||||||
"environment.cpp", "environment.h",
|
"environment.cpp", "environment.h",
|
||||||
|
"filepath.cpp", "filepath.h",
|
||||||
"fileutils.cpp", "fileutils.h",
|
"fileutils.cpp", "fileutils.h",
|
||||||
"hostosinfo.cpp", "hostosinfo.h",
|
"hostosinfo.cpp", "hostosinfo.h",
|
||||||
"namevaluedictionary.cpp", "namevaluedictionary.h",
|
"namevaluedictionary.cpp", "namevaluedictionary.h",
|
||||||
|
@@ -19,6 +19,7 @@ HEADERS += \
|
|||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$UTILSDIR/commandline.cpp \
|
$$UTILSDIR/commandline.cpp \
|
||||||
$$UTILSDIR/environment.cpp \
|
$$UTILSDIR/environment.cpp \
|
||||||
|
$$UTILSDIR/filepath.cpp \
|
||||||
$$UTILSDIR/fileutils.cpp \
|
$$UTILSDIR/fileutils.cpp \
|
||||||
$$UTILSDIR/hostosinfo.cpp \
|
$$UTILSDIR/hostosinfo.cpp \
|
||||||
$$UTILSDIR/launcherinterface.cpp \
|
$$UTILSDIR/launcherinterface.cpp \
|
||||||
@@ -34,6 +35,7 @@ HEADERS += \
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$UTILSDIR/commandline.h \
|
$$UTILSDIR/commandline.h \
|
||||||
$$UTILSDIR/environment.h \
|
$$UTILSDIR/environment.h \
|
||||||
|
$$UTILSDIR/filepath.h \
|
||||||
$$UTILSDIR/fileutils.h \
|
$$UTILSDIR/fileutils.h \
|
||||||
$$UTILSDIR/hostosinfo.h \
|
$$UTILSDIR/hostosinfo.h \
|
||||||
$$UTILSDIR/launcherinterface.h \
|
$$UTILSDIR/launcherinterface.h \
|
||||||
|
Reference in New Issue
Block a user