forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/11.0' into qds/dev
Conflicts: src/plugins/qmldesigner/designercore/metainfo/metainfo.cpp src/plugins/qmlprojectmanager/cmakegen/generatecmakelists.cpp tests/auto/qml/qmlprojectmanager/fileformat/fileformat.qbs tests/auto/qml/qmlprojectmanager/fileformat/tst_fileformat.cpp Change-Id: I257f1908917bcc58805619b53b6866f2f73ca544
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
add_subdirectory(3rdparty)
|
||||
add_subdirectory(buildoutputparser)
|
||||
|
||||
option(BUILD_CPLUSPLUS_TOOLS "Build CPlusPlus tools" OFF)
|
||||
|
||||
function(add_qtc_cpp_tool name)
|
||||
add_qtc_executable(${name}
|
||||
SKIP_INSTALL
|
||||
DEFINES
|
||||
PATH_PREPROCESSOR_CONFIG=\"${CMAKE_CURRENT_SOURCE_DIR}/cplusplus-shared/pp-configuration.inc\"
|
||||
${ARGN}
|
||||
@@ -17,12 +16,10 @@ function(add_qtc_cpp_tool name)
|
||||
)
|
||||
endfunction()
|
||||
|
||||
if (BUILD_CPLUSPLUS_TOOLS)
|
||||
add_qtc_cpp_tool(cplusplus-ast2png "")
|
||||
add_qtc_cpp_tool(cplusplus-frontend "")
|
||||
add_qtc_cpp_tool(cplusplus-mkvisitor PATH_AST_H=\"${CMAKE_CURRENT_SOURCE_DIR}/../libs/3rdparty/cplusplus/AST.h\")
|
||||
add_qtc_cpp_tool(cplusplus-update-frontend PATH_CPP_FRONTEND=\"${CMAKE_CURRENT_SOURCE_DIR}/../libs/3rdparty/cplusplus\" PATH_DUMPERS_FILE=\"${CMAKE_CURRENT_SOURCE_DIR}/cplusplus-ast2png/dumpers.inc\")
|
||||
endif()
|
||||
add_qtc_cpp_tool(cplusplus-ast2png "")
|
||||
add_qtc_cpp_tool(cplusplus-frontend "")
|
||||
add_qtc_cpp_tool(cplusplus-mkvisitor PATH_AST_H=\"${CMAKE_CURRENT_SOURCE_DIR}/../libs/3rdparty/cplusplus/AST.h\")
|
||||
add_qtc_cpp_tool(cplusplus-update-frontend PATH_CPP_FRONTEND=\"${CMAKE_CURRENT_SOURCE_DIR}/../libs/3rdparty/cplusplus\" PATH_DUMPERS_FILE=\"${CMAKE_CURRENT_SOURCE_DIR}/cplusplus-ast2png/dumpers.inc\")
|
||||
|
||||
if (APPLE)
|
||||
add_subdirectory(disclaim)
|
||||
@@ -46,3 +43,5 @@ add_subdirectory(wininterrupt) ## windows only
|
||||
if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/perfparser/CMakeLists.txt)
|
||||
add_subdirectory(perfparser)
|
||||
endif()
|
||||
|
||||
add_subdirectory(process_stub)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import qbs 1.0
|
||||
|
||||
QtcTool {
|
||||
install: false
|
||||
Depends { name: "Qt"; submodules: ["core", "widgets"]; }
|
||||
Depends { name: "CPlusPlus" }
|
||||
Depends { name: "Utils" }
|
||||
|
||||
@@ -3,7 +3,6 @@ import qbs.Environment
|
||||
|
||||
Project {
|
||||
name: "CPlusPlus Tools"
|
||||
condition: Environment.getEnv("BUILD_CPLUSPLUS_TOOLS")
|
||||
references: [
|
||||
"3rdparty/cplusplus-keywordgen/cplusplus-keywordgen.qbs",
|
||||
"cplusplus-ast2png/cplusplus-ast2png.qbs",
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
This directory needs to contain the files
|
||||
|
||||
icon_128x128.png
|
||||
icon_128x128@2x.png
|
||||
icon_16x16.png
|
||||
icon_16x16@2x.png
|
||||
icon_256x256.png
|
||||
icon_256x256@2x.png
|
||||
icon_32x32.png
|
||||
icon_32x32@2x.png
|
||||
icon_512x512.png
|
||||
icon_512x512@2x.png
|
||||
|
||||
On OSX, they are obtainable by executing the following command:
|
||||
iconutil -c iconset /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericDocumentIcon.icns
|
||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 79 KiB |
@@ -1,879 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="2104"
|
||||
height="4713"
|
||||
id="svg3397"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="documenttypeicons.svg"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs3399">
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath6024">
|
||||
<rect
|
||||
style="fill:none;stroke:none"
|
||||
id="rect6026"
|
||||
width="87"
|
||||
height="100"
|
||||
x="225"
|
||||
y="-5429" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="27.375271"
|
||||
inkscape:cy="533.28239"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer3"
|
||||
showgrid="true"
|
||||
inkscape:window-width="2880"
|
||||
inkscape:window-height="1503"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="527"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-grids="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3405"
|
||||
empspacing="1"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="false"
|
||||
dotted="true"
|
||||
originx="-16"
|
||||
originy="-7436" />
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3407"
|
||||
empspacing="1"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="false"
|
||||
spacingx="4px"
|
||||
spacingy="4px"
|
||||
originx="-16"
|
||||
originy="-7436" />
|
||||
<sodipodi:guide
|
||||
position="266,-6734"
|
||||
orientation="0,1"
|
||||
id="guide4571" />
|
||||
<sodipodi:guide
|
||||
position="1,-7431"
|
||||
orientation="0,1"
|
||||
id="guide4573" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata3402">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="qt-logos"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-16,11096.638)" />
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="qt-appicons"
|
||||
transform="translate(-16,11069)">
|
||||
<g
|
||||
id="uifile_icon_16x16"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-1036)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_16x16.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_16x16.png"
|
||||
y="-5336"
|
||||
x="16"
|
||||
id="image3192"
|
||||
height="16"
|
||||
width="16" />
|
||||
<rect
|
||||
y="-5325"
|
||||
x="27.62998"
|
||||
height="2.9999692"
|
||||
width="2.3699887"
|
||||
id="rect4308-8"
|
||||
style="fill:#cd9aa3;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
id="path4291-2"
|
||||
d="m 19,-5324 -1,0.5082 1,0.4918 z"
|
||||
style="fill:#47484a;fill-opacity:1;stroke:none"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<g
|
||||
id="tinyqt"
|
||||
transform="translate(-50,-5859)">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5089"
|
||||
d="m 78,532.5 -1.5,1.5 -6.5,0 0,-4.5 1.5,-1.5 3.484375,-0.004 0,0.99807 3,0.002 z"
|
||||
style="opacity:1;fill:#41cd52;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<g
|
||||
id="g4959"
|
||||
style="stroke:#ffffff;stroke-width:0.89999998;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
transform="translate(-2,-2)">
|
||||
<path
|
||||
sodipodi:nodetypes="zzzzz"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4945"
|
||||
d="m 74.5,531.5 c 1,0 1,0.28518 1,1.5 0,1.21481 0,1.5 -1,1.5 -1,0 -1,-0.30273 -1,-1.5 0,-1.19726 0,-1.5 1,-1.5 z"
|
||||
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4953"
|
||||
d="m 75.309359,534.5 1.198874,1.38951"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4955"
|
||||
d="m 77.484375,530.9963 0,2.89815 c 0.0017,0.96521 0.846972,0.77673 1.515655,0.60555"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4957"
|
||||
d="m 76.5,532.5 2.5,0"
|
||||
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.89999998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4286-4"
|
||||
d="m 21,-5325 -2,1 0,1 2,1 z"
|
||||
style="fill:#e1cab0;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="-5325.0005"
|
||||
x="21"
|
||||
height="1.999"
|
||||
width="6"
|
||||
id="rect4296-5"
|
||||
style="fill:#f7ec07;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
style="fill:#f7aa03;fill-opacity:1;stroke:none"
|
||||
id="rect4298-5"
|
||||
width="6"
|
||||
height="1.9999794"
|
||||
x="21"
|
||||
y="-5324" />
|
||||
<rect
|
||||
style="fill:#fbcb00;fill-opacity:1;stroke:none"
|
||||
id="rect4300-1"
|
||||
width="6"
|
||||
height="0.99998969"
|
||||
x="21"
|
||||
y="-5324" />
|
||||
<rect
|
||||
style="fill:#e4e6e7;fill-opacity:1;stroke:none"
|
||||
id="rect4302-7"
|
||||
width="1"
|
||||
height="0.99998969"
|
||||
x="26.98"
|
||||
y="-5325" />
|
||||
<rect
|
||||
y="-5323"
|
||||
x="26.98"
|
||||
height="0.99998969"
|
||||
width="1"
|
||||
id="rect4304-1"
|
||||
style="fill:#aeb1b3;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="-5324"
|
||||
x="26.98"
|
||||
height="0.99998969"
|
||||
width="1"
|
||||
id="rect4306-1"
|
||||
style="fill:#c8c9c9;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
<g
|
||||
id="uifile_icon_32x32"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-1036)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_32x32.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_32x32.png"
|
||||
y="-5352"
|
||||
x="32"
|
||||
id="image3203"
|
||||
height="32"
|
||||
width="32" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510"
|
||||
y="-6087.4551"
|
||||
x="39.699661"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.71243429px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.1435936,0.87443651)"><tspan
|
||||
id="tspan3514"
|
||||
y="-6087.4551"
|
||||
x="39.699661"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold'">UI</tspan></text>
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_16x16.png"
|
||||
xlink:href="designer_icon_16x16.png"
|
||||
width="16"
|
||||
height="16"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image5338"
|
||||
x="40"
|
||||
y="-5344" />
|
||||
</g>
|
||||
<g
|
||||
id="uifile_icon_128x128"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-1036)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_128x128.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_128x128.png"
|
||||
y="-5448"
|
||||
x="200"
|
||||
id="image3214"
|
||||
height="128"
|
||||
width="128" />
|
||||
<g
|
||||
id="g4328"
|
||||
clip-path="url(#clipPath6024)"
|
||||
transform="translate(-1.6893267,0.99880497)">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#text3510"
|
||||
id="use4326"
|
||||
transform="matrix(2.3826256,0,0,2.9999998,149.91558,10637.104)"
|
||||
width="1920"
|
||||
height="1080" />
|
||||
</g>
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_64x64.png"
|
||||
xlink:href="designer_icon_64x64.png"
|
||||
width="64"
|
||||
height="64"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image5457"
|
||||
x="232"
|
||||
y="-5416" />
|
||||
</g>
|
||||
<g
|
||||
id="uifile_icon_256x256"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-1036)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_256x256.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_256x256.png"
|
||||
y="-5576"
|
||||
x="328"
|
||||
id="image3225"
|
||||
height="256"
|
||||
width="256" />
|
||||
<use
|
||||
height="1080"
|
||||
width="1920"
|
||||
transform="matrix(2,0,0,2,-72,5315.173)"
|
||||
id="use4332"
|
||||
xlink:href="#g4328"
|
||||
y="0"
|
||||
x="0" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_128x128.png"
|
||||
xlink:href="designer_icon_128x128.png"
|
||||
y="-5512"
|
||||
x="392"
|
||||
id="image6519"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
preserveAspectRatio="none"
|
||||
height="128"
|
||||
width="128" />
|
||||
</g>
|
||||
<g
|
||||
id="uifile_icon_512x512"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-1036)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_512x512.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_512x512.png"
|
||||
y="-5832"
|
||||
x="584"
|
||||
id="image3236"
|
||||
height="512"
|
||||
width="512" />
|
||||
<use
|
||||
height="1080"
|
||||
width="1920"
|
||||
transform="matrix(2,0,0,2,-72,5320.6089)"
|
||||
id="use4334"
|
||||
xlink:href="#use4332"
|
||||
y="0"
|
||||
x="0" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_256x256.png"
|
||||
xlink:href="designer_icon_256x256.png"
|
||||
width="256"
|
||||
height="256"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4519"
|
||||
x="712"
|
||||
y="-5704" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-1560)"
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
id="uifile_icon_16x16@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_16x16@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_16x16@2x.png"
|
||||
width="32"
|
||||
height="32"
|
||||
id="image4080"
|
||||
x="32"
|
||||
y="-5352" />
|
||||
<text
|
||||
transform="scale(1.0533249,0.94937471)"
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:4.34046173px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
x="43.44009"
|
||||
y="-5606.9463"
|
||||
id="text4082"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold'"
|
||||
sodipodi:role="line"
|
||||
x="43.44009"
|
||||
y="-5606.9463"
|
||||
id="tspan4084">UI</tspan></text>
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_16x16.png"
|
||||
xlink:href="designer_icon_16x16.png"
|
||||
width="16"
|
||||
height="16"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image5349"
|
||||
x="40"
|
||||
y="-5344" />
|
||||
</g>
|
||||
<g
|
||||
id="uifile_icon_32x32@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_32x32@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_32x32@2x.png"
|
||||
y="-6944"
|
||||
x="64"
|
||||
id="image4120"
|
||||
height="64"
|
||||
width="64" />
|
||||
<use
|
||||
height="1"
|
||||
width="1"
|
||||
id="use4442"
|
||||
xlink:href="#g4328"
|
||||
y="0"
|
||||
x="0"
|
||||
transform="matrix(0.5,0,0,0.5,-35.699029,-4220.9125)" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_32x32.png"
|
||||
xlink:href="designer_icon_32x32.png"
|
||||
width="32"
|
||||
height="32"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4508"
|
||||
x="80"
|
||||
y="-6928" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-1560)"
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
id="uifile_icon_128x128@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_128x128@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_128x128@2x.png"
|
||||
width="256"
|
||||
height="256"
|
||||
id="image4101"
|
||||
x="328"
|
||||
y="-5576" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g4328"
|
||||
id="use4104"
|
||||
transform="matrix(2,0,0,2,-72,5315.173)"
|
||||
width="1920"
|
||||
height="1080" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_128x128.png"
|
||||
xlink:href="designer_icon_128x128.png"
|
||||
y="-5512"
|
||||
x="392"
|
||||
id="image6508"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
preserveAspectRatio="none"
|
||||
height="128"
|
||||
width="128" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-1560)"
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
id="uifile_icon_256x256@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_256x256@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_256x256@2x.png"
|
||||
width="512"
|
||||
height="512"
|
||||
id="image4108"
|
||||
x="584"
|
||||
y="-5832" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#use4332"
|
||||
id="use4110"
|
||||
transform="matrix(2,0,0,2,-72,5320.6089)"
|
||||
width="1920"
|
||||
height="1080" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_256x256.png"
|
||||
xlink:href="designer_icon_256x256.png"
|
||||
width="256"
|
||||
height="256"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4497"
|
||||
x="712"
|
||||
y="-5704" />
|
||||
</g>
|
||||
<g
|
||||
id="uifile_icon_512x512@2x"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_512x512@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_512x512@2x.png"
|
||||
y="-7905"
|
||||
x="1096"
|
||||
id="image4131"
|
||||
height="1024"
|
||||
width="1024" />
|
||||
<use
|
||||
height="1080"
|
||||
width="1920"
|
||||
transform="matrix(4,0,0,4,-216,14404.292)"
|
||||
id="use5743"
|
||||
xlink:href="#use4332"
|
||||
y="0"
|
||||
x="0" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\designer_icon_512x512.png"
|
||||
xlink:href="designer_icon_512x512.png"
|
||||
width="512"
|
||||
height="512"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4530"
|
||||
x="1352"
|
||||
y="-7649" />
|
||||
</g>
|
||||
<g
|
||||
id="qtcreator-project_icon_16x16"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-2600)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_16x16.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_16x16.png"
|
||||
width="16"
|
||||
height="16"
|
||||
id="image3192-0"
|
||||
x="16"
|
||||
y="-5336" />
|
||||
<use
|
||||
transform="translate(-0.015625,0.01594865)"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#tinyqt"
|
||||
id="use4802"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<g
|
||||
id="qtcreator-project_icon_32x32"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-2600)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_32x32.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_32x32.png"
|
||||
width="32"
|
||||
height="32"
|
||||
id="image3203-1"
|
||||
x="32"
|
||||
y="-5352" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_16x16.png"
|
||||
xlink:href="qtcreator_icon_16x16.png"
|
||||
width="16"
|
||||
height="16"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4838"
|
||||
x="40"
|
||||
y="-5344" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4"
|
||||
y="-5421.4678"
|
||||
x="40.865314"
|
||||
style="font-style:normal;font-weight:normal;font-size:5.29114771px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182219)"><tspan
|
||||
id="tspan3514-7"
|
||||
y="-5421.4678"
|
||||
x="40.865314"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold'">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="qtcreator-project_icon_128x128"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-2600)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_128x128.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_128x128.png"
|
||||
width="128"
|
||||
height="128"
|
||||
id="image3214-5"
|
||||
x="200"
|
||||
y="-5448" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_64x64.png"
|
||||
xlink:href="qtcreator_icon_64x64.png"
|
||||
width="64"
|
||||
height="64"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4860"
|
||||
x="232"
|
||||
y="-5416" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-4"
|
||||
y="-5432.687"
|
||||
x="258.93604"
|
||||
style="font-style:normal;font-weight:normal;font-size:12.62162399px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182216)"><tspan
|
||||
id="tspan3514-7-2"
|
||||
y="-5432.687"
|
||||
x="258.93604"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold';text-align:center;text-anchor:middle">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="qtcreator-project_icon_256x256"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-2600)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_256x256.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_256x256.png"
|
||||
width="256"
|
||||
height="256"
|
||||
id="image3225-9"
|
||||
x="328"
|
||||
y="-5576" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_128x128.png"
|
||||
xlink:href="qtcreator_icon_128x128.png"
|
||||
width="128"
|
||||
height="128"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4882"
|
||||
x="392"
|
||||
y="-5512" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-4-1"
|
||||
y="-5446.8779"
|
||||
x="447.18082"
|
||||
style="font-style:normal;font-weight:normal;font-size:25.24324799px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182216)"><tspan
|
||||
id="tspan3514-7-2-7"
|
||||
y="-5446.8779"
|
||||
x="447.18082"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold';text-align:center;text-anchor:middle">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="qtcreator-project_icon_512x512"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
transform="translate(0,-2600)">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_512x512.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_512x512.png"
|
||||
width="512"
|
||||
height="512"
|
||||
id="image3236-4"
|
||||
x="584"
|
||||
y="-5832" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_256x256.png"
|
||||
xlink:href="qtcreator_icon_256x256.png"
|
||||
width="256"
|
||||
height="256"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4904"
|
||||
x="712"
|
||||
y="-5704" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-4-79"
|
||||
y="-5475.2593"
|
||||
x="823.67059"
|
||||
style="font-style:normal;font-weight:normal;font-size:50.48649597px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182216)"><tspan
|
||||
id="tspan3514-7-2-3"
|
||||
y="-5475.2593"
|
||||
x="823.67059"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold';text-align:center;text-anchor:middle">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-3124)"
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
id="qtcreator-project_icon_16x16@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_16x16@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_16x16@2x.png"
|
||||
y="-5352"
|
||||
x="32"
|
||||
id="image4080-8"
|
||||
height="32"
|
||||
width="32" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_16x16.png"
|
||||
xlink:href="qtcreator_icon_16x16.png"
|
||||
y="-5344"
|
||||
x="40"
|
||||
id="image4827"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
preserveAspectRatio="none"
|
||||
height="16"
|
||||
width="16" />
|
||||
<use
|
||||
transform="translate(0.8660239,-0.03536906)"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#text3510-4"
|
||||
id="use5027"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-1564)"
|
||||
id="qtcreator-project_icon_32x32@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_32x32@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_32x32@2x.png"
|
||||
width="64"
|
||||
height="64"
|
||||
id="image4120-3"
|
||||
x="64"
|
||||
y="-6944" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_32x32.png"
|
||||
xlink:href="qtcreator_icon_32x32.png"
|
||||
width="32"
|
||||
height="32"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4849"
|
||||
x="80"
|
||||
y="-6928" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-9"
|
||||
y="-6551.9634"
|
||||
x="91.546913"
|
||||
style="font-style:normal;font-weight:normal;font-size:7.6833334px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(0.9513572,1.0511299)"><tspan
|
||||
id="tspan3514-7-8"
|
||||
y="-6551.9634"
|
||||
x="91.546913"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold'">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-3124)"
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
id="qtcreator-project_icon_128x128@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_128x128@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_128x128@2x.png"
|
||||
y="-5576"
|
||||
x="328"
|
||||
id="image4101-4"
|
||||
height="256"
|
||||
width="256" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_128x128.png"
|
||||
xlink:href="qtcreator_icon_128x128.png"
|
||||
width="128"
|
||||
height="128"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4871"
|
||||
x="392"
|
||||
y="-5512" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-4-7"
|
||||
y="-5446.8779"
|
||||
x="447.18088"
|
||||
style="font-style:normal;font-weight:normal;font-size:25.24324799px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182216)"><tspan
|
||||
id="tspan3514-7-2-5"
|
||||
y="-5446.8779"
|
||||
x="447.18088"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold';text-align:center;text-anchor:middle">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-3124)"
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:export-xdpi="90"
|
||||
id="qtcreator-project_icon_256x256@2x">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_256x256@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_256x256@2x.png"
|
||||
y="-5832"
|
||||
x="584"
|
||||
id="image4108-5"
|
||||
height="512"
|
||||
width="512" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_256x256.png"
|
||||
xlink:href="qtcreator_icon_256x256.png"
|
||||
width="256"
|
||||
height="256"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4893"
|
||||
x="712"
|
||||
y="-5704" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-4-77"
|
||||
y="-5473.2202"
|
||||
x="823.67059"
|
||||
style="font-style:normal;font-weight:normal;font-size:50.48649597px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182216)"><tspan
|
||||
id="tspan3514-7-2-6"
|
||||
y="-5473.2202"
|
||||
x="823.67059"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold';text-align:center;text-anchor:middle">PRO</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(0,-1564)"
|
||||
id="qtcreator-project_icon_512x512@2x"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\GenericDocumentIcon.iconset\icon_512x512@2x.png"
|
||||
xlink:href="GenericDocumentIcon.iconset\icon_512x512@2x.png"
|
||||
width="1024"
|
||||
height="1024"
|
||||
id="image4131-2"
|
||||
x="1096"
|
||||
y="-7905" />
|
||||
<image
|
||||
sodipodi:absref="C:\Users\aportale\dev\qtcreator-super\qtcreator\src\tools\icons\qtcreator_icon_512x512.png"
|
||||
xlink:href="qtcreator_icon_512x512.png"
|
||||
width="512"
|
||||
height="512"
|
||||
preserveAspectRatio="none"
|
||||
style="image-rendering:optimizeSpeed"
|
||||
id="image4915"
|
||||
x="1352"
|
||||
y="-7649" />
|
||||
<text
|
||||
sodipodi:linespacing="125%"
|
||||
id="text3510-4-4-11"
|
||||
y="-7121.9185"
|
||||
x="1576.6501"
|
||||
style="font-style:normal;font-weight:normal;font-size:100.97299194px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
|
||||
xml:space="preserve"
|
||||
transform="scale(1.0185144,0.98182216)"><tspan
|
||||
id="tspan3514-7-2-0"
|
||||
y="-7121.9185"
|
||||
x="1576.6501"
|
||||
sodipodi:role="line"
|
||||
style="font-weight:bold;-inkscape-font-specification:'Sans Bold';text-align:center;text-anchor:middle">PRO</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="app-icon-images"
|
||||
transform="translate(-16,11069)" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 31 KiB |
@@ -1,102 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2016 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
# This script creates several application icon files by using
|
||||
# Inkscape to rasterize .svg items to .png, adding shadows via
|
||||
# imagemagick, creating .ico files via imagemagick and .icns
|
||||
# files via iconutil (OSX only).
|
||||
|
||||
# optipng is required by this script
|
||||
if ! hash optipng 2>/dev/null; then
|
||||
echo "optipng was not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Imagemagick convert is required by this script
|
||||
if ! hash convert 2>/dev/null; then
|
||||
echo "Imagemagick convert was not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
applicationNames="qtcreator designer linguist assistant qdbusviewer qmlviewer"
|
||||
applicationIconDimensions="16:0 24:0 32:1 48:1 64:1 128:2 256:3 512:7 1024:15"
|
||||
|
||||
# Creating the list of svg IDs to export
|
||||
for applicationName in $applicationNames;\
|
||||
do
|
||||
for applicationIconDimension in $applicationIconDimensions;\
|
||||
do
|
||||
applicationIconSize=`echo $applicationIconDimension | awk -F: '{ print $1 }'`
|
||||
iconIDs="${iconIDs} ${applicationName}_icon_${applicationIconSize}x${applicationIconSize}"
|
||||
done
|
||||
done
|
||||
|
||||
# Copying the logos for Qt Creator's sources. Without shadows!
|
||||
creatorLogoDir="logo"
|
||||
rm -rf $creatorLogoDir
|
||||
mkdir $creatorLogoDir
|
||||
for uiFileIconSize in 16 24 32 48 64 128 256 512;\
|
||||
do
|
||||
creatorLogoSource="qtcreator_icon_${uiFileIconSize}x${uiFileIconSize}.png"
|
||||
creatorLogoTargetDir="${creatorLogoDir}/${uiFileIconSize}"
|
||||
creatorLogoTarget="${creatorLogoTargetDir}/QtProject-qtcreator.png"
|
||||
optipng $creatorLogoSource -o 7 -strip all
|
||||
mkdir $creatorLogoTargetDir
|
||||
cp $creatorLogoSource $creatorLogoTarget
|
||||
done
|
||||
|
||||
# Adding the shadows to the .png files
|
||||
for applicationName in $applicationNames;\
|
||||
do
|
||||
for applicationIconDimension in $applicationIconDimensions;\
|
||||
do
|
||||
iconSize=`echo $applicationIconDimension | awk -F: '{ print $1 }'`
|
||||
shadowSize=`echo $applicationIconDimension | awk -F: '{ print $2 }'`
|
||||
iconFile=${applicationName}_icon_${iconSize}x${iconSize}.png
|
||||
if [ "$shadowSize" != "0" ]
|
||||
then
|
||||
convert -page ${iconSize}x${iconSize} ${iconFile} \( +clone -background black -shadow 25x1+0+0 \) +swap -background none -flatten ${iconFile}
|
||||
convert -page ${iconSize}x${iconSize} ${iconFile} \( +clone -background black -shadow 40x${shadowSize}+0+${shadowSize} \) +swap -background none -flatten ${iconFile}
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Creating the .ico files
|
||||
iconSizes="256 128 64 48 32 24 16"
|
||||
for applicationName in $applicationNames;\
|
||||
do
|
||||
icoFiles=""
|
||||
for iconSize in $iconSizes;\
|
||||
do
|
||||
icoFiles="$icoFiles ${applicationName}_icon_${iconSize}x${iconSize}.png"
|
||||
done
|
||||
convert ${icoFiles} ${applicationName}.ico
|
||||
done
|
||||
|
||||
# Optimizing the .pngs
|
||||
for iconID in $iconIDs;\
|
||||
do
|
||||
optipng "${iconID}.png" -o 7 -strip all
|
||||
done
|
||||
|
||||
# Preparing application .iconsets for the conversion to .icns
|
||||
for applicationName in $applicationNames;\
|
||||
do
|
||||
inconsetName=${applicationName}.iconset
|
||||
rm -rf $inconsetName
|
||||
mkdir $inconsetName
|
||||
cp ${applicationName}_icon_16x16.png ${inconsetName}/icon_16x16.png
|
||||
cp ${applicationName}_icon_32x32.png ${inconsetName}/icon_32x32.png
|
||||
cp ${applicationName}_icon_128x128.png ${inconsetName}/icon_128x128.png
|
||||
cp ${applicationName}_icon_256x256.png ${inconsetName}/icon_256x256.png
|
||||
cp ${applicationName}_icon_512x512.png ${inconsetName}/icon_512x512.png
|
||||
cp ${applicationName}_icon_32x32.png ${inconsetName}/icon_16x16@2x.png
|
||||
cp ${applicationName}_icon_64x64.png ${inconsetName}/icon_32x32@2x.png
|
||||
cp ${applicationName}_icon_256x256.png ${inconsetName}/icon_128x128@2x.png
|
||||
cp ${applicationName}_icon_512x512.png ${inconsetName}/icon_256x256@2x.png
|
||||
cp ${applicationName}_icon_1024x1024.png ${inconsetName}/icon_512x512@2x.png
|
||||
done
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2016 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
# optipng is required by this script
|
||||
if ! hash optipng 2>/dev/null; then
|
||||
echo "optipng was not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
# Adding the icons for the OSX document type icon for .ui files
|
||||
for documentTypeName in "uifile" "qtcreator-project";\
|
||||
do
|
||||
inconsetName=${documentTypeName}.iconset
|
||||
rm -rf $inconsetName
|
||||
mkdir $inconsetName
|
||||
for iconSize in 16 32 128 256 512;\
|
||||
do
|
||||
iconShortID="icon_${iconSize}x${iconSize}"
|
||||
iconLongID="${documentTypeName}_${iconShortID}"
|
||||
for sizeVariation in "" "@2x";\
|
||||
do
|
||||
iconSourcePng="${iconLongID}${sizeVariation}.png"
|
||||
iconTargetPng="${inconsetName}/${iconShortID}${sizeVariation}.png"
|
||||
optipng $iconSourcePng -o 7 -strip all
|
||||
cp $iconSourcePng $iconTargetPng
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -653,6 +653,14 @@
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="matrix(1.5,0,0,1.5,0,-242)" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#backgroundRect"
|
||||
id="backgroundRect_12"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="matrix(0.75,0,0,0.75,-24,97)" />
|
||||
<rect
|
||||
y="452"
|
||||
x="-16"
|
||||
@@ -2965,7 +2973,7 @@
|
||||
<use
|
||||
height="100%"
|
||||
width="100%"
|
||||
transform="matrix(-1,0,0,1,2336,0)"
|
||||
transform="matrix(-1,0,0,1,2338,0)"
|
||||
id="use6797"
|
||||
xlink:href="#g6795"
|
||||
y="0"
|
||||
@@ -3147,6 +3155,68 @@
|
||||
d="m 1078,478.85469 1.189,13.30208 m -4.1861,-1.62746 L 1086.5,495 m -17,0 9.272,-7.52758"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/terminal/images/settingscategory_terminal">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#backgroundRect_24"
|
||||
id="use4838"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(1115,64)"
|
||||
style="display:inline;fill:none" />
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-opacity:1.0"
|
||||
id="rect2040"
|
||||
width="15"
|
||||
height="12"
|
||||
x="1095.5"
|
||||
y="481.5" />
|
||||
<path
|
||||
id="path5004"
|
||||
style="fill:none;stroke:#000000;stroke-opacity:1.0"
|
||||
d="m 1100,488.5 h 3 m -5.75,-5.25 2.25,2.25 -2.25,2.25" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/copilot/images/settingscategory_copilot">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#backgroundRect_24"
|
||||
id="use4838-1"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(1141,64)" />
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#src/plugins/copilot/images/copilot"
|
||||
id="use13883"
|
||||
style="display:inline"
|
||||
transform="matrix(1.3271416,0,0,1.27511,-1468.1838,-246.66424)" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/haskell/images/settingscategory_haskell">
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#backgroundRect_24"
|
||||
id="use5402"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(1166,64)" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
d="m 1150,482 h 2.5 l 8.67,13 h -2.5 l -3.085,-4.625 L 1152.51,495 h -2.5 l 4.335,-6.5 z"
|
||||
id="path7771"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
id="path10150-5"
|
||||
style="fill:#606060;fill-opacity:1"
|
||||
d="m 1160,491 h 2 v -2 h -3.335 z m -2,-3 h 4 v -2 h -5.335 z m -9.5,-6 4.335,6.5 -4.335,6.5 h -2.5 l 4.335,-6.5 L 1146,482 Z"
|
||||
sodipodi:nodetypes="ccccccccccccccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/valgrind/images/kcachegrind"
|
||||
transform="translate(112)">
|
||||
@@ -3484,6 +3554,56 @@
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/terminal/images/terminal">
|
||||
<use
|
||||
style="display:inline"
|
||||
transform="translate(1948,132)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="use1987"
|
||||
xlink:href="#backgroundRect"
|
||||
y="0"
|
||||
x="0" />
|
||||
<path
|
||||
id="path5004-3"
|
||||
style="fill:none;stroke:#000000"
|
||||
d="m 1936.25,571.25 2.25,2.25 -2.25,2.25 m -2.75,-6.25 h 8 v 8 h -8 z" />
|
||||
</g>
|
||||
<g
|
||||
id="src/plugins/copilot/images/copilot"
|
||||
transform="translate(828,88.5)"
|
||||
style="display:inline">
|
||||
<use
|
||||
style="display:inline"
|
||||
transform="translate(1137,43.5)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
id="use1987-3"
|
||||
xlink:href="#backgroundRect"
|
||||
y="0"
|
||||
x="0" />
|
||||
<g
|
||||
id="g2022"
|
||||
transform="translate(0,0.5)">
|
||||
<path
|
||||
style="fill:#000000"
|
||||
d="m 1135,493 c 0,0 0,-4.5 0,-6 0,-2 -0.5,-6 -6,-6 v 6 c 5,2.5 6,6 6,6 z"
|
||||
id="path5346"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
id="path7819"
|
||||
style="fill:#ffffff;stroke:none"
|
||||
d="m 1130,484.5 c 0,1.23611 0.4442,2.26438 1.9319,2.54447 1.4877,0.28009 2.0454,-1.0336 2.0454,-1.97641 0,-0.94281 -0.4262,-1.72947 -1.9539,-2.12425 -1.5277,-0.39477 -2.0185,0.32008 -2.0234,1.55619 z m -1.002,-0.5 v 1 h 0.502 v -1 z m -0.01,2 c 0.012,4.5 1.012,3.5 5.0083,5.5 V 488 l -0.16,-0.63611 c -1.2971,1.18069 -3.8728,0.64494 -4.34,-1.36389 z"
|
||||
sodipodi:nodetypes="zsszzccccccccccc" />
|
||||
</g>
|
||||
<use
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#g2022"
|
||||
id="use3673"
|
||||
transform="matrix(-1,0,0,1,2258,0)" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
@@ -6453,6 +6573,27 @@
|
||||
d="m 347,597.33936 0.60019,0.60645 3.49128,-3.49127 3.09695,3.09695 c 0.29088,-0.96173 0.20375,-2.0863 -0.1875,-3.07155 l 3.68179,-3.68179 0.55968,0.52841 0.75761,-0.75762 -4.51473,-4.51475 -0.80193,0.80194 0.53076,0.51509 -3.60205,3.60206 c -1.04768,-0.37523 -2.22553,-0.48941 -3.20237,-0.15625 l 3.0615,3.0615 z"
|
||||
style="fill:#000000" />
|
||||
</g>
|
||||
<g
|
||||
id="src/libs/utils/images/pinned_small">
|
||||
<use
|
||||
style="display:inline"
|
||||
x="0"
|
||||
y="0"
|
||||
xlink:href="#backgroundRect_12"
|
||||
id="use1988"
|
||||
width="100%"
|
||||
height="100%"
|
||||
transform="translate(397,160)" />
|
||||
<g
|
||||
id="g6007"
|
||||
transform="rotate(45,366.14645,589.64645)">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
d="m 369.5,585 v 1 h -1 l 0.5,3 h 1 v 1 h -2.5 l -0.2,5 h -0.6 l -0.2,-5 H 364 v -1 h 1 l 0.5,-3 h -1 v -1 z"
|
||||
id="path5401"
|
||||
sodipodi:nodetypes="ccccccccccccccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
@@ -9250,6 +9391,20 @@
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="src/libs/utils/images/iconoverlay_close_small">
|
||||
<rect
|
||||
id="rect5336"
|
||||
height="16"
|
||||
width="16"
|
||||
y="363"
|
||||
x="649"
|
||||
style="fill:#ffffff" />
|
||||
<path
|
||||
id="path4779-7"
|
||||
style="stroke:#000000;stroke-width:2"
|
||||
d="m 656.5,370.5 7,7 m -7,0 7,-7" />
|
||||
</g>
|
||||
<g
|
||||
id="src/libs/utils/images/iconoverlay_add"
|
||||
transform="translate(112)">
|
||||
|
||||
|
Before Width: | Height: | Size: 356 KiB After Width: | Height: | Size: 361 KiB |
Submodule src/tools/perfparser updated: ac05977da7...5444f96207
12
src/tools/process_stub/CMakeLists.txt
Normal file
12
src/tools/process_stub/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
add_qtc_executable(qtcreator_process_stub
|
||||
DEPENDS Qt::Core Qt::Network
|
||||
SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
extend_qtc_executable(qtcreator_process_stub
|
||||
DEFINES _UNICODE UNICODE _CRT_SECURE_NO_WARNINGS
|
||||
)
|
||||
endif()
|
||||
572
src/tools/process_stub/main.cpp
Normal file
572
src/tools/process_stub/main.cpp
Normal file
@@ -0,0 +1,572 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QLocalSocket>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMutex>
|
||||
#include <QProcess>
|
||||
#include <QSocketNotifier>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QWinEventNotifier>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <optional>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <sys/ptrace.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Q_LOGGING_CATEGORY(log, "qtc.process_stub", QtWarningMsg);
|
||||
|
||||
// Global variables
|
||||
|
||||
QCommandLineParser commandLineParser;
|
||||
|
||||
// The inferior command and arguments
|
||||
QStringList inferiorCmdAndArguments;
|
||||
// Whether to Suspend the inferior process on startup (to allow a debugger to attach)
|
||||
bool debugMode = false;
|
||||
// Whether to run in test mode (i.e. to start manually from the command line)
|
||||
bool testMode = false;
|
||||
// The control socket used to communicate with Qt Creator
|
||||
QLocalSocket controlSocket;
|
||||
// Environment variables to set for the inferior process
|
||||
std::optional<QStringList> environmentVariables;
|
||||
|
||||
QProcess inferiorProcess;
|
||||
int inferiorId{0};
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
// A memory mapped helper to retrieve the pid of the inferior process in debugMode
|
||||
static int *shared_child_pid = nullptr;
|
||||
#endif
|
||||
|
||||
using OSSocketNotifier = QSocketNotifier;
|
||||
#else
|
||||
Q_PROCESS_INFORMATION *win_process_information = nullptr;
|
||||
using OSSocketNotifier = QWinEventNotifier;
|
||||
#endif
|
||||
// Helper to read a single character from stdin in testMode
|
||||
OSSocketNotifier *stdInNotifier;
|
||||
|
||||
QThread processThread;
|
||||
|
||||
// Helper to create the shared memory mapped segment
|
||||
void setupSharedPid();
|
||||
// Parses the command line, returns a status code in case of error
|
||||
std::optional<int> tryParseCommandLine(QCoreApplication &app);
|
||||
// Sets the working directory, returns a status code in case of error
|
||||
std::optional<int> trySetWorkingDir();
|
||||
// Reads the environment variables from the env file, returns a status code in case of error
|
||||
std::optional<int> readEnvFile();
|
||||
|
||||
void setupControlSocket();
|
||||
void setupSignalHandlers();
|
||||
void startProcess(const QString &program, const QStringList &arguments, const QString &workingDir);
|
||||
void readKey();
|
||||
void sendSelfPid();
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
setupSharedPid();
|
||||
|
||||
auto error = tryParseCommandLine(a);
|
||||
if (error)
|
||||
return error.value();
|
||||
|
||||
qCInfo(log) << "Debug helper started: ";
|
||||
qCInfo(log) << "Socket:" << commandLineParser.value("socket");
|
||||
qCInfo(log) << "Inferior:" << inferiorCmdAndArguments.join(QChar::Space);
|
||||
qCInfo(log) << "Working Directory" << commandLineParser.value("workingDir");
|
||||
qCInfo(log) << "Env file:" << commandLineParser.value("envfile");
|
||||
qCInfo(log) << "Mode:"
|
||||
<< QLatin1String(testMode ? "test | " : "")
|
||||
+ QLatin1String(debugMode ? "debug" : "run");
|
||||
|
||||
error = trySetWorkingDir();
|
||||
if (error)
|
||||
return error.value();
|
||||
|
||||
error = readEnvFile();
|
||||
if (error)
|
||||
return error.value();
|
||||
|
||||
if (testMode) {
|
||||
sendSelfPid();
|
||||
setupSignalHandlers();
|
||||
|
||||
startProcess(inferiorCmdAndArguments[0],
|
||||
inferiorCmdAndArguments.mid(1),
|
||||
commandLineParser.value("workingDir"));
|
||||
|
||||
if (debugMode) {
|
||||
qDebug() << "Press 'c' to continue or 'k' to kill, followed by 'enter'";
|
||||
readKey();
|
||||
}
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
setupControlSocket();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
void sendMsg(const QByteArray &msg)
|
||||
{
|
||||
if (controlSocket.state() == QLocalSocket::ConnectedState) {
|
||||
controlSocket.write(msg);
|
||||
} else {
|
||||
qDebug() << "MSG:" << msg;
|
||||
}
|
||||
}
|
||||
|
||||
void sendPid(int inferiorPid)
|
||||
{
|
||||
sendMsg(QString("pid %1\n").arg(inferiorPid).toUtf8());
|
||||
}
|
||||
|
||||
void sendThreadId(int inferiorThreadPid)
|
||||
{
|
||||
sendMsg(QString("thread %1\n").arg(inferiorThreadPid).toUtf8());
|
||||
}
|
||||
|
||||
void sendSelfPid()
|
||||
{
|
||||
sendMsg(QString("spid %1\n").arg(QCoreApplication::applicationPid()).toUtf8());
|
||||
}
|
||||
|
||||
void sendExit(int exitCode)
|
||||
{
|
||||
sendMsg(QString("exit %1\n").arg(exitCode).toUtf8());
|
||||
}
|
||||
|
||||
void sendCrash(int exitCode)
|
||||
{
|
||||
sendMsg(QString("crash %1\n").arg(exitCode).toUtf8());
|
||||
}
|
||||
|
||||
void sendErrChDir()
|
||||
{
|
||||
sendMsg(QString("err:chdir %1\n").arg(errno).toUtf8());
|
||||
}
|
||||
|
||||
void doExit(int exitCode)
|
||||
{
|
||||
if (controlSocket.state() == QLocalSocket::ConnectedState && controlSocket.bytesToWrite())
|
||||
controlSocket.waitForBytesWritten(1000);
|
||||
|
||||
if (!commandLineParser.value("wait").isEmpty()) {
|
||||
std::cout << commandLineParser.value("wait").toStdString();
|
||||
std::cin.get();
|
||||
}
|
||||
|
||||
exit(exitCode);
|
||||
}
|
||||
|
||||
void onInferiorFinished(int exitCode, QProcess::ExitStatus status)
|
||||
{
|
||||
qCInfo(log) << "Inferior finished";
|
||||
|
||||
if (status == QProcess::CrashExit) {
|
||||
sendCrash(exitCode);
|
||||
doExit(exitCode);
|
||||
} else {
|
||||
sendExit(exitCode);
|
||||
doExit(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
void onInferiorErrorOccurered(QProcess::ProcessError error)
|
||||
{
|
||||
qCInfo(log) << "Inferior error: " << error << inferiorProcess.errorString();
|
||||
sendCrash(inferiorProcess.exitCode());
|
||||
doExit(1);
|
||||
}
|
||||
|
||||
void onInferiorStarted()
|
||||
{
|
||||
inferiorId = inferiorProcess.processId();
|
||||
qCInfo(log) << "Inferior started ( pid:" << inferiorId << ")";
|
||||
#ifdef Q_OS_WIN
|
||||
sendThreadId(win_process_information->dwThreadId);
|
||||
sendPid(inferiorId);
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
// In debug mode we use the poll timer to send the pid.
|
||||
if (!debugMode)
|
||||
sendPid(inferiorId);
|
||||
#else
|
||||
ptrace(PTRACE_DETACH, inferiorId, 0, SIGSTOP);
|
||||
sendPid(inferiorId);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setupUnixInferior()
|
||||
{
|
||||
#ifndef Q_OS_WIN
|
||||
if (debugMode) {
|
||||
qCInfo(log) << "Debug mode enabled";
|
||||
#ifdef Q_OS_DARWIN
|
||||
// We are using raise(SIGSTOP) to stop the child process, macOS does not support ptrace(...)
|
||||
inferiorProcess.setChildProcessModifier([] {
|
||||
// Let the parent know our pid ...
|
||||
*shared_child_pid = getpid();
|
||||
// Suspend ourselves ...
|
||||
raise(SIGSTOP);
|
||||
});
|
||||
#else
|
||||
// PTRACE_TRACEME will stop execution of the child process as soon as execve is called.
|
||||
inferiorProcess.setChildProcessModifier([] { ptrace(PTRACE_TRACEME, 0, 0, 0); });
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void setupWindowsInferior()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
inferiorProcess.setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
|
||||
if (debugMode)
|
||||
args->flags |= CREATE_SUSPENDED;
|
||||
win_process_information = args->processInformation;
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void setupPidPollTimer()
|
||||
{
|
||||
#ifdef Q_OS_DARWIN
|
||||
if (!debugMode)
|
||||
return;
|
||||
|
||||
static QTimer pollPidTimer;
|
||||
|
||||
pollPidTimer.setInterval(1);
|
||||
pollPidTimer.setSingleShot(false);
|
||||
QObject::connect(&pollPidTimer, &QTimer::timeout, &pollPidTimer, [&] {
|
||||
if (*shared_child_pid) {
|
||||
qCInfo(log) << "Received pid during polling:" << *shared_child_pid;
|
||||
inferiorId = *shared_child_pid;
|
||||
sendPid(inferiorId);
|
||||
pollPidTimer.stop();
|
||||
munmap(shared_child_pid, sizeof(int));
|
||||
} else {
|
||||
qCDebug(log) << "Waiting for inferior to start...";
|
||||
}
|
||||
});
|
||||
pollPidTimer.start();
|
||||
#endif
|
||||
}
|
||||
|
||||
enum class Out { StdOut, StdErr };
|
||||
|
||||
void writeToOut(const QByteArray &data, Out out)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
static const HANDLE outHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
static const HANDLE errHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
WriteFile(out == Out::StdOut ? outHandle : errHandle,
|
||||
data.constData(),
|
||||
data.size(),
|
||||
nullptr,
|
||||
nullptr);
|
||||
#else
|
||||
auto fp = out == Out::StdOut ? stdout : stderr;
|
||||
::fwrite(data.constData(), 1, data.size(), fp);
|
||||
::fflush(fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void startProcess(const QString &executable, const QStringList &arguments, const QString &workingDir)
|
||||
{
|
||||
setupPidPollTimer();
|
||||
|
||||
qCInfo(log) << "Starting Inferior";
|
||||
|
||||
QObject::connect(&inferiorProcess,
|
||||
&QProcess::finished,
|
||||
QCoreApplication::instance(),
|
||||
&onInferiorFinished);
|
||||
QObject::connect(&inferiorProcess,
|
||||
&QProcess::errorOccurred,
|
||||
QCoreApplication::instance(),
|
||||
&onInferiorErrorOccurered);
|
||||
QObject::connect(&inferiorProcess,
|
||||
&QProcess::started,
|
||||
QCoreApplication::instance(),
|
||||
&onInferiorStarted);
|
||||
|
||||
inferiorProcess.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
|
||||
if (!(testMode && debugMode))
|
||||
inferiorProcess.setInputChannelMode(QProcess::ForwardedInputChannel);
|
||||
inferiorProcess.setWorkingDirectory(workingDir);
|
||||
inferiorProcess.setProgram(executable);
|
||||
inferiorProcess.setArguments(arguments);
|
||||
|
||||
if (environmentVariables)
|
||||
inferiorProcess.setEnvironment(*environmentVariables);
|
||||
|
||||
setupWindowsInferior();
|
||||
setupUnixInferior();
|
||||
|
||||
inferiorProcess.start();
|
||||
}
|
||||
|
||||
std::optional<int> readEnvFile()
|
||||
{
|
||||
if (!commandLineParser.isSet("envfile"))
|
||||
return std::nullopt;
|
||||
|
||||
const QString path = commandLineParser.value("envfile");
|
||||
qCInfo(log) << "Reading env file: " << path << "...";
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qCWarning(log) << "Failed to open env file: " << path;
|
||||
return 1;
|
||||
}
|
||||
|
||||
environmentVariables = QStringList{};
|
||||
|
||||
while (!file.atEnd()) {
|
||||
QByteArray data = file.readAll();
|
||||
if (!data.isEmpty()) {
|
||||
for (const auto &line : data.split('\0')) {
|
||||
if (!line.isEmpty())
|
||||
*environmentVariables << QString::fromUtf8(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(log) << "Env: ";
|
||||
for (const auto &env : *environmentVariables)
|
||||
qCDebug(log) << env;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
void forwardSignal(int signum)
|
||||
{
|
||||
qCDebug(log) << "SIGTERM received, terminating inferior...";
|
||||
kill(inferiorId, signum);
|
||||
}
|
||||
#else
|
||||
static BOOL WINAPI ctrlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT) {
|
||||
qCDebug(log) << "Terminate inferior...";
|
||||
inferiorProcess.terminate();
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void setupSignalHandlers()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
SetConsoleCtrlHandler(ctrlHandler, TRUE);
|
||||
#else
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
if (sigaction(SIGTTOU, &act, NULL)) {
|
||||
qCWarning(log) << "sigaction SIGTTOU: " << strerror(errno);
|
||||
doExit(3);
|
||||
}
|
||||
|
||||
act.sa_handler = forwardSignal;
|
||||
if (sigaction(SIGTERM, &act, NULL)) {
|
||||
qCWarning(log) << "sigaction SIGTERM: " << strerror(errno);
|
||||
doExit(3);
|
||||
}
|
||||
|
||||
if (sigaction(SIGINT, &act, NULL)) {
|
||||
qCWarning(log) << "sigaction SIGINT: " << strerror(errno);
|
||||
doExit(3);
|
||||
}
|
||||
|
||||
qCDebug(log) << "Signals set up";
|
||||
#endif
|
||||
}
|
||||
|
||||
std::optional<int> tryParseCommandLine(QCoreApplication &app)
|
||||
{
|
||||
commandLineParser.setApplicationDescription("Debug helper for QtCreator");
|
||||
commandLineParser.addHelpOption();
|
||||
commandLineParser.addOption(QCommandLineOption({"d", "debug"}, "Start inferior in debug mode"));
|
||||
commandLineParser.addOption(QCommandLineOption({"t", "test"}, "Don't start the control socket"));
|
||||
commandLineParser.addOption(
|
||||
QCommandLineOption({"s", "socket"}, "Path to the unix socket", "socket"));
|
||||
commandLineParser.addOption(
|
||||
QCommandLineOption({"w", "workingDir"}, "Working directory for inferior", "workingDir"));
|
||||
commandLineParser.addOption(QCommandLineOption({"v", "verbose"}, "Print debug messages"));
|
||||
commandLineParser.addOption(QCommandLineOption({"e", "envfile"}, "Path to env file", "envfile"));
|
||||
commandLineParser.addOption(
|
||||
QCommandLineOption("wait",
|
||||
"Message to display to the user while waiting for key press",
|
||||
"waitmessage",
|
||||
"Press enter to continue ..."));
|
||||
|
||||
commandLineParser.process(app);
|
||||
|
||||
inferiorCmdAndArguments = commandLineParser.positionalArguments();
|
||||
debugMode = commandLineParser.isSet("debug");
|
||||
testMode = commandLineParser.isSet("test");
|
||||
|
||||
if (!(commandLineParser.isSet("socket") || testMode) || inferiorCmdAndArguments.isEmpty()) {
|
||||
commandLineParser.showHelp(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (commandLineParser.isSet("verbose"))
|
||||
QLoggingCategory::setFilterRules("qtc.process_stub=true");
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<int> trySetWorkingDir()
|
||||
{
|
||||
if (commandLineParser.isSet("workingDir")) {
|
||||
if (!QDir::setCurrent(commandLineParser.value("workingDir"))) {
|
||||
qCWarning(log) << "Failed to change working directory to: "
|
||||
<< commandLineParser.value("workingDir");
|
||||
sendErrChDir();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void setupSharedPid()
|
||||
{
|
||||
#ifdef Q_OS_DARWIN
|
||||
shared_child_pid = (int *) mmap(NULL,
|
||||
sizeof *shared_child_pid,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS,
|
||||
-1,
|
||||
0);
|
||||
*shared_child_pid = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void onControlSocketConnected()
|
||||
{
|
||||
qCInfo(log) << "Connected to control socket";
|
||||
|
||||
sendSelfPid();
|
||||
setupSignalHandlers();
|
||||
|
||||
startProcess(inferiorCmdAndArguments[0],
|
||||
inferiorCmdAndArguments.mid(1),
|
||||
commandLineParser.value("workingDir"));
|
||||
}
|
||||
|
||||
void resumeInferior()
|
||||
{
|
||||
qCDebug(log) << "Continuing inferior... (" << inferiorId << ")";
|
||||
#ifdef Q_OS_WIN
|
||||
ResumeThread(win_process_information->hThread);
|
||||
#else
|
||||
kill(inferiorId, SIGCONT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void killInferior()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
inferiorProcess.kill();
|
||||
#else
|
||||
kill(inferiorId, SIGKILL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void onControlSocketReadyRead()
|
||||
{
|
||||
//k = kill, i = interrupt, c = continue, s = shutdown
|
||||
QByteArray data = controlSocket.readAll();
|
||||
for (auto ch : data) {
|
||||
qCDebug(log) << "Received:" << ch;
|
||||
|
||||
switch (ch) {
|
||||
case 'k': {
|
||||
qCDebug(log) << "Killing inferior...";
|
||||
killInferior();
|
||||
break;
|
||||
}
|
||||
#ifndef Q_OS_WIN
|
||||
case 'i': {
|
||||
qCDebug(log) << "Interrupting inferior...";
|
||||
kill(inferiorId, SIGINT);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case 'c': {
|
||||
resumeInferior();
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
qCDebug(log) << "Shutting down...";
|
||||
doExit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onControlSocketErrorOccurred(QLocalSocket::LocalSocketError socketError)
|
||||
{
|
||||
qCWarning(log) << "Control socket error:" << socketError;
|
||||
doExit(1);
|
||||
}
|
||||
|
||||
void setupControlSocket()
|
||||
{
|
||||
QObject::connect(&controlSocket, &QLocalSocket::connected, &onControlSocketConnected);
|
||||
QObject::connect(&controlSocket, &QLocalSocket::readyRead, &onControlSocketReadyRead);
|
||||
QObject::connect(&controlSocket, &QLocalSocket::errorOccurred, &onControlSocketErrorOccurred);
|
||||
|
||||
qCInfo(log) << "Waiting for connection...";
|
||||
controlSocket.connectToServer(commandLineParser.value("socket"));
|
||||
}
|
||||
|
||||
void onStdInReadyRead()
|
||||
{
|
||||
char ch;
|
||||
std::cin >> ch;
|
||||
if (ch == 'k') {
|
||||
killInferior();
|
||||
} else {
|
||||
resumeInferior();
|
||||
}
|
||||
}
|
||||
|
||||
void readKey()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
stdInNotifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
|
||||
#else
|
||||
stdInNotifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read);
|
||||
#endif
|
||||
QObject::connect(stdInNotifier, &OSSocketNotifier::activated, &onStdInReadyRead);
|
||||
}
|
||||
10
src/tools/process_stub/process_stub.qbs
Normal file
10
src/tools/process_stub/process_stub.qbs
Normal file
@@ -0,0 +1,10 @@
|
||||
import qbs 1.0
|
||||
|
||||
QtcTool {
|
||||
name: "qtcreator_process_stub"
|
||||
consoleApplication: true
|
||||
|
||||
Depends { name: "Qt"; submodules: ["core", "network"]; }
|
||||
|
||||
files: [ "main.cpp" ]
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
set(LIBSDIR "${PROJECT_SOURCE_DIR}/src/libs")
|
||||
set(UTILSDIR "${PROJECT_SOURCE_DIR}/src/libs/utils")
|
||||
|
||||
add_qtc_executable(qtcreator_processlauncher
|
||||
INCLUDES "${UTILSDIR}"
|
||||
INCLUDES "${LIBSDIR}"
|
||||
DEPENDS Qt::Core Qt::Network
|
||||
DEFINES UTILS_STATIC_LIBRARY
|
||||
SOURCES
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "launchersockethandler.h"
|
||||
|
||||
#include "launcherlogging.h"
|
||||
#include "processreaper.h"
|
||||
#include "processutils.h"
|
||||
|
||||
#include <utils/processreaper.h>
|
||||
#include <utils/processutils.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QLocalSocket>
|
||||
@@ -14,11 +14,11 @@
|
||||
namespace Utils {
|
||||
namespace Internal {
|
||||
|
||||
class Process : public ProcessHelper
|
||||
class ProcessWithToken : public ProcessHelper
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Process(quintptr token, QObject *parent = nullptr) :
|
||||
ProcessWithToken(quintptr token, QObject *parent = nullptr) :
|
||||
ProcessHelper(parent), m_token(token) { }
|
||||
|
||||
quintptr token() const { return m_token; }
|
||||
@@ -41,7 +41,7 @@ LauncherSocketHandler::LauncherSocketHandler(QString serverPath, QObject *parent
|
||||
LauncherSocketHandler::~LauncherSocketHandler()
|
||||
{
|
||||
for (auto it = m_processes.cbegin(); it != m_processes.cend(); ++it) {
|
||||
Process *p = it.value();
|
||||
ProcessWithToken *p = it.value();
|
||||
if (p->state() != QProcess::NotRunning)
|
||||
logWarn(QStringLiteral("Shutting down while process %1 is running").arg(p->program()));
|
||||
ProcessReaper::reap(p);
|
||||
@@ -114,7 +114,7 @@ void LauncherSocketHandler::handleSocketClosed()
|
||||
qApp->quit();
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleProcessError(Process *process)
|
||||
void LauncherSocketHandler::handleProcessError(ProcessWithToken *process)
|
||||
{
|
||||
// In case of FailedToStart we won't receive finished signal, so we send the error
|
||||
// packet and remove the process here and now. For all other errors we should expect
|
||||
@@ -124,7 +124,7 @@ void LauncherSocketHandler::handleProcessError(Process *process)
|
||||
handleProcessFinished(process);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleProcessStarted(Process *process)
|
||||
void LauncherSocketHandler::handleProcessStarted(ProcessWithToken *process)
|
||||
{
|
||||
ProcessStartedPacket packet(process->token());
|
||||
packet.processId = process->processId();
|
||||
@@ -132,21 +132,21 @@ void LauncherSocketHandler::handleProcessStarted(Process *process)
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleReadyReadStandardOutput(Process *process)
|
||||
void LauncherSocketHandler::handleReadyReadStandardOutput(ProcessWithToken *process)
|
||||
{
|
||||
ReadyReadStandardOutputPacket packet(process->token());
|
||||
packet.standardChannel = process->readAllStandardOutput();
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleReadyReadStandardError(Process *process)
|
||||
void LauncherSocketHandler::handleReadyReadStandardError(ProcessWithToken *process)
|
||||
{
|
||||
ReadyReadStandardErrorPacket packet(process->token());
|
||||
packet.standardChannel = process->readAllStandardError();
|
||||
sendPacket(packet);
|
||||
}
|
||||
|
||||
void LauncherSocketHandler::handleProcessFinished(Process *process)
|
||||
void LauncherSocketHandler::handleProcessFinished(ProcessWithToken *process)
|
||||
{
|
||||
ProcessDonePacket packet(process->token());
|
||||
packet.exitCode = process->exitCode();
|
||||
@@ -162,7 +162,7 @@ void LauncherSocketHandler::handleProcessFinished(Process *process)
|
||||
|
||||
void LauncherSocketHandler::handleStartPacket()
|
||||
{
|
||||
Process *& process = m_processes[m_packetParser.token()];
|
||||
ProcessWithToken *& process = m_processes[m_packetParser.token()];
|
||||
if (!process)
|
||||
process = setupProcess(m_packetParser.token());
|
||||
if (process->state() != QProcess::NotRunning) {
|
||||
@@ -172,6 +172,7 @@ void LauncherSocketHandler::handleStartPacket()
|
||||
const auto packet = LauncherPacket::extractPacket<StartProcessPacket>(
|
||||
m_packetParser.token(),
|
||||
m_packetParser.packetData());
|
||||
|
||||
process->setEnvironment(packet.env);
|
||||
process->setWorkingDirectory(packet.workingDir);
|
||||
// Forwarding is handled by the LauncherInterface
|
||||
@@ -179,10 +180,10 @@ void LauncherSocketHandler::handleStartPacket()
|
||||
? QProcess::MergedChannels : QProcess::SeparateChannels);
|
||||
process->setStandardInputFile(packet.standardInputFile);
|
||||
ProcessStartHandler *handler = process->processStartHandler();
|
||||
handler->setWindowsSpecificStartupFlags(packet.belowNormalPriority,
|
||||
packet.createConsoleOnWindows);
|
||||
handler->setProcessMode(packet.processMode);
|
||||
handler->setWriteData(packet.writeData);
|
||||
if (packet.belowNormalPriority)
|
||||
handler->setBelowNormalPriority();
|
||||
handler->setNativeArguments(packet.nativeArguments);
|
||||
if (packet.lowPriority)
|
||||
process->setLowPriority();
|
||||
@@ -196,7 +197,7 @@ void LauncherSocketHandler::handleStartPacket()
|
||||
|
||||
void LauncherSocketHandler::handleWritePacket()
|
||||
{
|
||||
Process * const process = m_processes.value(m_packetParser.token());
|
||||
ProcessWithToken * const process = m_processes.value(m_packetParser.token());
|
||||
if (!process) {
|
||||
logWarn("Got write request for unknown process");
|
||||
return;
|
||||
@@ -213,7 +214,7 @@ void LauncherSocketHandler::handleWritePacket()
|
||||
|
||||
void LauncherSocketHandler::handleControlPacket()
|
||||
{
|
||||
Process * const process = m_processes.value(m_packetParser.token());
|
||||
ProcessWithToken * const process = m_processes.value(m_packetParser.token());
|
||||
if (!process) {
|
||||
// This can happen when the process finishes on its own at about the same time the client
|
||||
// sends the request. In this case the process was already deleted.
|
||||
@@ -252,9 +253,9 @@ void LauncherSocketHandler::sendPacket(const LauncherPacket &packet)
|
||||
m_socket->write(packet.serialize());
|
||||
}
|
||||
|
||||
Process *LauncherSocketHandler::setupProcess(quintptr token)
|
||||
ProcessWithToken *LauncherSocketHandler::setupProcess(quintptr token)
|
||||
{
|
||||
const auto p = new Process(token, this);
|
||||
const auto p = new ProcessWithToken(token, this);
|
||||
connect(p, &QProcess::started, this, [this, p] { handleProcessStarted(p); });
|
||||
connect(p, &QProcess::errorOccurred, this, [this, p] { handleProcessError(p); });
|
||||
connect(p, &QProcess::finished, this, [this, p] { handleProcessFinished(p); });
|
||||
@@ -271,7 +272,7 @@ void LauncherSocketHandler::removeProcess(quintptr token)
|
||||
if (it == m_processes.constEnd())
|
||||
return;
|
||||
|
||||
Process *process = it.value();
|
||||
ProcessWithToken *process = it.value();
|
||||
m_processes.erase(it);
|
||||
ProcessReaper::reap(process, process->reaperTimeout());
|
||||
}
|
||||
@@ -279,4 +280,4 @@ void LauncherSocketHandler::removeProcess(quintptr token)
|
||||
} // namespace Internal
|
||||
} // namespace Utils
|
||||
|
||||
#include <launchersockethandler.moc>
|
||||
#include "launchersockethandler.moc"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <launcherpackets.h>
|
||||
#include <utils/launcherpackets.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
@@ -15,7 +15,7 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace Utils {
|
||||
namespace Internal {
|
||||
class Process;
|
||||
class ProcessWithToken;
|
||||
|
||||
class LauncherSocketHandler : public QObject
|
||||
{
|
||||
@@ -31,11 +31,11 @@ private:
|
||||
void handleSocketError();
|
||||
void handleSocketClosed();
|
||||
|
||||
void handleProcessStarted(Process *process);
|
||||
void handleProcessError(Process *process);
|
||||
void handleProcessFinished(Process *process);
|
||||
void handleReadyReadStandardOutput(Process *process);
|
||||
void handleReadyReadStandardError(Process *process);
|
||||
void handleProcessStarted(ProcessWithToken *process);
|
||||
void handleProcessError(ProcessWithToken *process);
|
||||
void handleProcessFinished(ProcessWithToken *process);
|
||||
void handleReadyReadStandardOutput(ProcessWithToken *process);
|
||||
void handleReadyReadStandardError(ProcessWithToken *process);
|
||||
|
||||
void handleStartPacket();
|
||||
void handleWritePacket();
|
||||
@@ -44,13 +44,13 @@ private:
|
||||
|
||||
void sendPacket(const LauncherPacket &packet);
|
||||
|
||||
Process *setupProcess(quintptr token);
|
||||
ProcessWithToken *setupProcess(quintptr token);
|
||||
void removeProcess(quintptr token);
|
||||
|
||||
const QString m_serverPath;
|
||||
QLocalSocket * const m_socket;
|
||||
PacketParser m_packetParser;
|
||||
QHash<quintptr, Process *> m_processes;
|
||||
QHash<quintptr, ProcessWithToken *> m_processes;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
#include "launcherlogging.h"
|
||||
#include "launchersockethandler.h"
|
||||
#include "singleton.h"
|
||||
|
||||
#include <utils/singleton.h>
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qscopeguard.h>
|
||||
|
||||
@@ -7,7 +7,7 @@ QtcTool {
|
||||
Depends { name: "Qt.network" }
|
||||
|
||||
cpp.defines: base.concat("UTILS_STATIC_LIBRARY")
|
||||
cpp.includePaths: base.concat(pathToUtils)
|
||||
cpp.includePaths: base.concat(pathToLibs)
|
||||
|
||||
Properties {
|
||||
condition: qbs.targetOS.contains("windows")
|
||||
@@ -24,6 +24,7 @@ QtcTool {
|
||||
"processlauncher-main.cpp",
|
||||
]
|
||||
|
||||
property string pathToLibs: sourceDirectory + "/../../libs"
|
||||
property string pathToUtils: sourceDirectory + "/../../libs/utils"
|
||||
Group {
|
||||
name: "protocol sources"
|
||||
|
||||
@@ -29,8 +29,6 @@ else()
|
||||
set(QT_VERSION_MAJOR ${Qt6_VERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
configure_file(../../app/app_version.h.cmakein app/app_version.h ESCAPE_QUOTES)
|
||||
|
||||
if (NOT TARGET QmlPuppetCommunication)
|
||||
include(../../libs/qmlpuppetcommunication/QmlPuppetCommunication.cmake)
|
||||
endif()
|
||||
@@ -46,28 +44,32 @@ add_qtc_executable(qml2puppet
|
||||
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
SOURCES
|
||||
qml2puppet/qml2puppetmain.cpp
|
||||
qml2puppet/qmlbase.h qml2puppet/appmetadata.h
|
||||
qml2puppet/qmlbase.h
|
||||
qml2puppet/appmetadata.cpp qml2puppet/appmetadata.h
|
||||
qml2puppet/qmlpuppet.h qml2puppet/qmlpuppet.cpp qml2puppet/configcrashpad.h
|
||||
qmlpuppet.qrc
|
||||
PROPERTIES
|
||||
OUTPUT_NAME qml2puppet-${IDE_VERSION}
|
||||
)
|
||||
|
||||
if(TARGET qml2puppet)
|
||||
if (TARGET qml2puppet)
|
||||
execute_process(
|
||||
COMMAND git describe --tags --always --dirty=+
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
RESULT_VARIABLE GIT_SHA_RESULT
|
||||
OUTPUT_VARIABLE GIT_SHA_OUTPUT
|
||||
OUTPUT_VARIABLE GIT_SHA
|
||||
ERROR_VARIABLE GIT_SHA_ERROR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
#if we are not a git repository use the .tag file
|
||||
if(NOT GIT_SHA_OUTPUT)
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/../../../.tag GIT_SHA_OUTPUT)
|
||||
if(NOT GIT_SHA)
|
||||
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/../../../.tag GIT_SHA LIMIT_COUNT 1)
|
||||
endif()
|
||||
|
||||
add_definitions( -D GIT_SHA=${GIT_SHA_OUTPUT} )
|
||||
set(IDE_REVISION_STR ${GIT_SHA})
|
||||
|
||||
configure_file(../../app/app_version.h.cmakein app/app_version.h ESCAPE_QUOTES)
|
||||
endif()
|
||||
|
||||
extend_qtc_executable(qml2puppet
|
||||
|
||||
51
src/tools/qml2puppet/qml2puppet/appmetadata.cpp
Normal file
51
src/tools/qml2puppet/qml2puppet/appmetadata.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "appmetadata.h"
|
||||
|
||||
#include <app/app_version.h>
|
||||
|
||||
namespace QDSMeta::AppInfo {
|
||||
|
||||
void printAppInfo()
|
||||
{
|
||||
qInfo() << Qt::endl
|
||||
<< "<< QDS Meta Info >>" << Qt::endl
|
||||
<< "App Info" << Qt::endl
|
||||
<< " - Name :" << Core::Constants::IDE_ID << Qt::endl
|
||||
<< " - Version :" << Core::Constants::IDE_VERSION_DISPLAY << Qt::endl
|
||||
<< " - Author :" << Core::Constants::IDE_AUTHOR << Qt::endl
|
||||
<< " - Year :" << Core::Constants::IDE_YEAR << Qt::endl
|
||||
<< " - App :" << QCoreApplication::applicationName() << Qt::endl
|
||||
<< "Build Info " << Qt::endl
|
||||
<< " - Date :" << __DATE__ << Qt::endl
|
||||
<< " - Commit :" << QStringLiteral(QDS_STRINGIFY(IDE_REVISION_STR)) << Qt::endl
|
||||
<< " - Qt Version :" << QT_VERSION_STR << Qt::endl
|
||||
<< "Compiler Info " << Qt::endl
|
||||
#if defined(__GNUC__)
|
||||
<< " - GCC :" << __GNUC__ << Qt::endl
|
||||
<< " - GCC Minor :" << __GNUC_MINOR__ << Qt::endl
|
||||
<< " - GCC Patch :" << __GNUC_PATCHLEVEL__ << Qt::endl
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
<< " - MSC Short :" << _MSC_VER << Qt::endl
|
||||
<< " - MSC Full :" << _MSC_FULL_VER << Qt::endl
|
||||
#endif
|
||||
#if defined(__clang__)
|
||||
<< " - clang maj :" << __clang_major__ << Qt::endl
|
||||
<< " - clang min :" << __clang_minor__ << Qt::endl
|
||||
<< " - clang patch :" << __clang_patchlevel__ << Qt::endl
|
||||
#endif
|
||||
<< "<< End Of QDS Meta Info >>" << Qt::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void registerAppInfo(const QString &appName)
|
||||
{
|
||||
QCoreApplication::setOrganizationName(Core::Constants::IDE_AUTHOR);
|
||||
QCoreApplication::setOrganizationDomain("qt-project.org");
|
||||
QCoreApplication::setApplicationName(appName);
|
||||
QCoreApplication::setApplicationVersion(Core::Constants::IDE_VERSION_LONG);
|
||||
}
|
||||
|
||||
} // namespace QDSMeta::AppInfo
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <QCommandLineParser>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <app/app_version.h>
|
||||
|
||||
// Common functions can be used in all QDS apps
|
||||
namespace QDSMeta {
|
||||
|
||||
@@ -50,46 +48,8 @@ namespace AppInfo {
|
||||
#define STRINGIFY_INTERNAL(x) #x
|
||||
#define QDS_STRINGIFY(x) STRINGIFY_INTERNAL(x)
|
||||
|
||||
inline void printAppInfo()
|
||||
{
|
||||
qInfo() << Qt::endl
|
||||
<< "<< QDS Meta Info >>" << Qt::endl
|
||||
<< "App Info" << Qt::endl
|
||||
<< " - Name :" << Core::Constants::IDE_ID << Qt::endl
|
||||
<< " - Version :" << Core::Constants::IDE_VERSION_DISPLAY << Qt::endl
|
||||
<< " - Author :" << Core::Constants::IDE_AUTHOR << Qt::endl
|
||||
<< " - Year :" << Core::Constants::IDE_YEAR << Qt::endl
|
||||
<< " - App :" << QCoreApplication::applicationName() << Qt::endl
|
||||
<< "Build Info " << Qt::endl
|
||||
<< " - Date :" << __DATE__ << Qt::endl
|
||||
<< " - Commit :" << QStringLiteral(QDS_STRINGIFY(GIT_SHA)) << Qt::endl
|
||||
<< " - Qt Version :" << QT_VERSION_STR << Qt::endl
|
||||
<< "Compiler Info " << Qt::endl
|
||||
#if defined(__GNUC__)
|
||||
<< " - GCC :" << __GNUC__ << Qt::endl
|
||||
<< " - GCC Minor :" << __GNUC_MINOR__ << Qt::endl
|
||||
<< " - GCC Patch :" << __GNUC_PATCHLEVEL__ << Qt::endl
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
<< " - MSC Short :" << _MSC_VER << Qt::endl
|
||||
<< " - MSC Full :" << _MSC_FULL_VER << Qt::endl
|
||||
#endif
|
||||
#if defined(__clang__)
|
||||
<< " - clang maj :" << __clang_major__ << Qt::endl
|
||||
<< " - clang min :" << __clang_minor__ << Qt::endl
|
||||
<< " - clang patch :" << __clang_patchlevel__ << Qt::endl
|
||||
#endif
|
||||
<< "<< End Of QDS Meta Info >>" << Qt::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
inline void registerAppInfo(const QString &appName)
|
||||
{
|
||||
QCoreApplication::setOrganizationName(Core::Constants::IDE_AUTHOR);
|
||||
QCoreApplication::setOrganizationDomain("qt-project.org");
|
||||
QCoreApplication::setApplicationName(appName);
|
||||
QCoreApplication::setApplicationVersion(Core::Constants::IDE_VERSION_LONG);
|
||||
}
|
||||
void printAppInfo();
|
||||
void registerAppInfo(const QString &appName);
|
||||
|
||||
} // namespace AppInfo
|
||||
} // namespace QDSMeta
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <sqlitelibraryinitializer.h>
|
||||
#endif
|
||||
|
||||
#include <app/app_version.h>
|
||||
#include <qml2puppet/iconrenderer/iconrenderer.h>
|
||||
#include <qml2puppet/import3d/import3d.h>
|
||||
|
||||
|
||||
@@ -520,7 +520,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (debug)
|
||||
qDebug() << "Mode=" << optMode << " PID=" << argProcessId << " Evt=" << argWinCrashEvent;
|
||||
bool ex = 0;
|
||||
int ex = 0;
|
||||
switch (optMode) {
|
||||
case HelpMode:
|
||||
usage(QCoreApplication::applicationFilePath(), errorMessage);
|
||||
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
QCoreApplication::quit();
|
||||
});
|
||||
|
||||
using namespace Utils::Layouting;
|
||||
using namespace Layouting;
|
||||
|
||||
Column {
|
||||
Row { m_iconLabel, m_introLabel, st },
|
||||
@@ -205,11 +205,11 @@ CrashHandlerDialog::~CrashHandlerDialog()
|
||||
bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
|
||||
{
|
||||
// Check settings.
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope,
|
||||
QSettings settings(QSettings::IniFormat,
|
||||
QSettings::UserScope,
|
||||
QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR),
|
||||
QLatin1String(SettingsApplication));
|
||||
if (settings.value(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), false).toBool())
|
||||
return true;
|
||||
Utils::CheckableMessageBox::initialize(&settings);
|
||||
|
||||
// Ask user.
|
||||
const QString title = tr("Run Debugger And Abort Collecting Backtrace?");
|
||||
@@ -219,15 +219,16 @@ bool CrashHandlerDialog::runDebuggerWhileBacktraceNotFinished()
|
||||
"<p>You have requested to run the debugger while collecting the backtrace was not "
|
||||
"finished.</p>"
|
||||
"</body></html>");
|
||||
const QString checkBoxText = tr("Do not &ask again.");
|
||||
bool checkBoxSetting = false;
|
||||
const QDialogButtonBox::StandardButton button = Utils::CheckableMessageBox::question(this,
|
||||
title, message, checkBoxText, &checkBoxSetting,
|
||||
QDialogButtonBox::Yes | QDialogButtonBox::No, QDialogButtonBox::No);
|
||||
if (checkBoxSetting)
|
||||
settings.setValue(QLatin1String(SettingsKeySkipWarningAbortingBacktrace), checkBoxSetting);
|
||||
|
||||
return button == QDialogButtonBox::Yes;
|
||||
const QMessageBox::StandardButton button
|
||||
= Utils::CheckableMessageBox::question(this,
|
||||
title,
|
||||
message,
|
||||
QString(SettingsKeySkipWarningAbortingBacktrace),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No);
|
||||
|
||||
return button == QMessageBox::Yes;
|
||||
}
|
||||
|
||||
void CrashHandlerDialog::setToFinalState()
|
||||
|
||||
@@ -66,33 +66,7 @@ add_qtc_library(sdktoolLib
|
||||
rmqtoperation.cpp rmqtoperation.h
|
||||
rmtoolchainoperation.cpp rmtoolchainoperation.h
|
||||
settings.cpp settings.h
|
||||
)
|
||||
|
||||
extend_qtc_library(sdktoolLib
|
||||
SOURCES_PREFIX "${UtilsSourcesDir}"
|
||||
PUBLIC_DEFINES UTILS_STATIC_LIBRARY
|
||||
SOURCES
|
||||
commandline.cpp commandline.h
|
||||
devicefileaccess.cpp devicefileaccess.h
|
||||
environment.cpp environment.h
|
||||
filepath.cpp filepath.h
|
||||
fileutils.cpp fileutils.h
|
||||
hostosinfo.cpp hostosinfo.h
|
||||
macroexpander.cpp macroexpander.h
|
||||
namevaluedictionary.cpp namevaluedictionary.h
|
||||
namevalueitem.cpp namevalueitem.h
|
||||
persistentsettings.cpp persistentsettings.h
|
||||
qtcassert.cpp qtcassert.h
|
||||
savefile.cpp savefile.h
|
||||
stringutils.cpp stringutils.h
|
||||
)
|
||||
|
||||
extend_qtc_library(sdktoolLib CONDITION APPLE
|
||||
SOURCES_PREFIX "${UtilsSourcesDir}"
|
||||
SOURCES
|
||||
fileutils_mac.mm fileutils_mac.h
|
||||
PUBLIC_DEPENDS
|
||||
${FWFoundation}
|
||||
sdkpersistentsettings.cpp sdkpersistentsettings.h
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
@@ -120,7 +94,7 @@ add_qtc_executable(sdktool
|
||||
main.cpp
|
||||
)
|
||||
|
||||
if (MSVC AND TARGET sdktool AND Qt5_VERSION VERSION_LESS 6.0.0)
|
||||
if (MSVC AND TARGET sdktool AND TARGET Qt5::Core)
|
||||
# find out if Qt is static and set /MT if so
|
||||
get_target_property(_input_type Qt5::Core TYPE)
|
||||
if (${_input_type} STREQUAL "STATIC_LIBRARY")
|
||||
|
||||
@@ -4,13 +4,10 @@
|
||||
#include "addcmakeoperation.h"
|
||||
|
||||
#include "addkeysoperation.h"
|
||||
#include "findkeyoperation.h"
|
||||
#include "findvalueoperation.h"
|
||||
#include "getoperation.h"
|
||||
#include "rmkeysoperation.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
#include <QTest>
|
||||
#endif
|
||||
@@ -205,7 +202,7 @@ QVariantMap AddCMakeData::addCMake(const QVariantMap &map) const
|
||||
data << KeyValuePair({cm, ID_KEY}, QVariant(m_id));
|
||||
data << KeyValuePair({cm, DISPLAYNAME_KEY}, QVariant(m_displayName));
|
||||
data << KeyValuePair({cm, AUTODETECTED_KEY}, QVariant(true));
|
||||
data << KeyValuePair({cm, PATH_KEY}, Utils::FilePath::fromUserInput(m_path).toVariant());
|
||||
data << KeyValuePair({cm, PATH_KEY}, QVariant(m_path));
|
||||
KeyValuePairList extraList;
|
||||
for (const KeyValuePair &pair : std::as_const(m_extra))
|
||||
extraList << KeyValuePair(QStringList({cm}) << pair.key, pair.value);
|
||||
|
||||
@@ -222,8 +222,7 @@ QVariantMap AddDebuggerData::addDebugger(const QVariantMap &map) const
|
||||
|
||||
data << KeyValuePair(QStringList() << debugger << QLatin1String(ABIS), QVariant(m_abis));
|
||||
data << KeyValuePair(QStringList() << debugger << QLatin1String(ENGINE_TYPE), QVariant(m_engine));
|
||||
data << KeyValuePair(QStringList() << debugger << QLatin1String(BINARY),
|
||||
Utils::FilePath::fromUserInput(m_binary).toSettings());
|
||||
data << KeyValuePair(QStringList() << debugger << QLatin1String(BINARY), QVariant(m_binary));
|
||||
|
||||
data << KeyValuePair(QStringList() << QLatin1String(COUNT), QVariant(count + 1));
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QLoggingCategory>
|
||||
#include <QRegularExpression>
|
||||
|
||||
@@ -685,8 +686,7 @@ QVariantMap AddKitData::addKit(const QVariantMap &map,
|
||||
if (!m_buildDevice.isNull())
|
||||
data << KeyValuePair({kit, DATA, BUILDDEVICE_ID}, QVariant(m_buildDevice));
|
||||
if (!m_sysRoot.isNull())
|
||||
data << KeyValuePair({kit, DATA, SYSROOT},
|
||||
Utils::FilePath::fromUserInput(m_sysRoot).toSettings());
|
||||
data << KeyValuePair({kit, DATA, SYSROOT}, QVariant(QDir::cleanPath(m_sysRoot)));
|
||||
for (auto i = m_tcs.constBegin(); i != m_tcs.constEnd(); ++i)
|
||||
data << KeyValuePair({kit, DATA, TOOLCHAIN, i.key()}, QVariant(i.value()));
|
||||
if (!qtId.isNull())
|
||||
|
||||
@@ -11,19 +11,16 @@
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <utils/filepath.h>
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
#include <QTest>
|
||||
#endif
|
||||
|
||||
#include <QDir>
|
||||
#include <QLoggingCategory>
|
||||
#include <QRegularExpression>
|
||||
|
||||
Q_LOGGING_CATEGORY(log, "qtc.sdktool.operations.addqt", QtWarningMsg)
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
// Qt version file stuff:
|
||||
const char PREFIX[] = "QtVersion.";
|
||||
const char VERSION[] = "Version";
|
||||
@@ -282,7 +279,7 @@ QVariantMap AddQtData::addQt(const QVariantMap &map) const
|
||||
const QString qt = QString::fromLatin1(PREFIX) + QString::number(versionCount);
|
||||
|
||||
// Sanitize qmake path:
|
||||
FilePath saneQmake = FilePath::fromUserInput(m_qmake).cleanPath();
|
||||
QString saneQmake = QDir::cleanPath(m_qmake);
|
||||
|
||||
// insert data:
|
||||
KeyValuePairList data;
|
||||
@@ -291,7 +288,7 @@ QVariantMap AddQtData::addQt(const QVariantMap &map) const
|
||||
data << KeyValuePair(QStringList() << qt << QLatin1String(AUTODETECTED), QVariant(true));
|
||||
data << KeyValuePair(QStringList() << qt << QLatin1String(AUTODETECTION_SOURCE), QVariant(sdkId));
|
||||
|
||||
data << KeyValuePair(QStringList() << qt << QLatin1String(QMAKE), saneQmake.toSettings());
|
||||
data << KeyValuePair(QStringList() << qt << QLatin1String(QMAKE), QVariant(saneQmake));
|
||||
data << KeyValuePair(QStringList() << qt << QLatin1String(TYPE), QVariant(m_type));
|
||||
data << KeyValuePair(QStringList() << qt << ABIS, QVariant(m_abis));
|
||||
|
||||
|
||||
@@ -4,13 +4,10 @@
|
||||
#include "addtoolchainoperation.h"
|
||||
|
||||
#include "addkeysoperation.h"
|
||||
#include "findkeyoperation.h"
|
||||
#include "findvalueoperation.h"
|
||||
#include "getoperation.h"
|
||||
#include "rmkeysoperation.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
@@ -283,7 +280,7 @@ QVariantMap AddToolChainData::addToolChain(const QVariantMap &map) const
|
||||
data << KeyValuePair({tc, LANGUAGE_KEY_V2}, QVariant(newLang));
|
||||
data << KeyValuePair({tc, DISPLAYNAME}, QVariant(m_displayName));
|
||||
data << KeyValuePair({tc, AUTODETECTED}, QVariant(true));
|
||||
data << KeyValuePair({tc, PATH}, Utils::FilePath::fromUserInput(m_path).toSettings());
|
||||
data << KeyValuePair({tc, PATH}, QVariant(m_path));
|
||||
data << KeyValuePair({tc, TARGET_ABI}, QVariant(m_targetAbi));
|
||||
QVariantList abis;
|
||||
const QStringList abiStrings = m_supportedAbis.split(',');
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
#include <app/app_version.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QStringList>
|
||||
|
||||
@@ -60,10 +62,7 @@ void printHelp(const std::vector<std::unique_ptr<Operation>> &operations)
|
||||
std::cout << " --sdkpath=PATH|-s PATH Set the path to the SDK files" << std::endl << std::endl;
|
||||
|
||||
std::cout << "Default sdkpath is \""
|
||||
<< qPrintable(QDir::cleanPath(
|
||||
Utils::FilePath::fromString(QCoreApplication::applicationDirPath())
|
||||
.pathAppended(DATA_PATH)
|
||||
.toUserOutput()))
|
||||
<< qPrintable(QDir::cleanPath(QCoreApplication::applicationDirPath() + '/' + DATA_PATH))
|
||||
<< "\"" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
@@ -105,7 +104,7 @@ int parseArguments(const QStringList &args, Settings *s,
|
||||
|
||||
// sdkpath
|
||||
if (current.startsWith(QLatin1String("--sdkpath="))) {
|
||||
s->sdkPath = Utils::FilePath::fromString(current.mid(10));
|
||||
s->sdkPath = current.mid(10);
|
||||
continue;
|
||||
}
|
||||
if (current == QLatin1String("-s")) {
|
||||
@@ -114,7 +113,7 @@ int parseArguments(const QStringList &args, Settings *s,
|
||||
printHelp(operations);
|
||||
return 1;
|
||||
}
|
||||
s->sdkPath = Utils::FilePath::fromString(next);
|
||||
s->sdkPath = next;
|
||||
++i; // skip next;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
#include "operation.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <utils/persistentsettings.h>
|
||||
#include "sdkpersistentsettings.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
@@ -65,9 +64,9 @@ QVariantMap Operation::load(const QString &file)
|
||||
QVariantMap map;
|
||||
|
||||
// Read values from original file:
|
||||
Utils::FilePath path = Settings::instance()->getPath(file);
|
||||
if (path.exists()) {
|
||||
Utils::PersistentSettingsReader reader;
|
||||
QString path = Settings::instance()->getPath(file);
|
||||
if (QFileInfo::exists(path)) {
|
||||
SdkPersistentSettingsReader reader;
|
||||
if (!reader.load(path))
|
||||
return QVariantMap();
|
||||
map = reader.restoreValues();
|
||||
@@ -78,32 +77,32 @@ QVariantMap Operation::load(const QString &file)
|
||||
|
||||
bool Operation::save(const QVariantMap &map, const QString &file) const
|
||||
{
|
||||
Utils::FilePath path = Settings::instance()->getPath(file);
|
||||
QString path = Settings::instance()->getPath(file);
|
||||
|
||||
if (path.isEmpty()) {
|
||||
std::cerr << "Error: No path found for " << qPrintable(file) << "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Utils::FilePath dirName = path.parentDir();
|
||||
QDir dir(dirName.toString());
|
||||
QString dirName = QDir::cleanPath(path + "/..");
|
||||
QDir dir(dirName);
|
||||
if (!dir.exists() && !dir.mkpath(QLatin1String("."))) {
|
||||
std::cerr << "Error: Could not create directory " << qPrintable(dirName.toString())
|
||||
std::cerr << "Error: Could not create directory " << qPrintable(dirName)
|
||||
<< "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Utils::PersistentSettingsWriter writer(path, QLatin1String("QtCreator")
|
||||
SdkPersistentSettingsWriter writer(path, QLatin1String("QtCreator")
|
||||
+ file[0].toUpper() + file.mid(1));
|
||||
QString errorMessage;
|
||||
if (!writer.save(map, &errorMessage)) {
|
||||
std::cerr << "Error: Could not save settings " << qPrintable(path.toString())
|
||||
std::cerr << "Error: Could not save settings " << qPrintable(path)
|
||||
<< "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!path.setPermissions(QFile::ReadOwner | QFile::WriteOwner
|
||||
if (!QFile(path).setPermissions(QFile::ReadOwner | QFile::WriteOwner
|
||||
| QFile::ReadGroup | QFile::ReadOther)) {
|
||||
std::cerr << "Error: Could not set permissions for " << qPrintable(path.toString())
|
||||
std::cerr << "Error: Could not set permissions for " << qPrintable(path)
|
||||
<< "." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
|
||||
871
src/tools/sdktool/sdkpersistentsettings.cpp
Normal file
871
src/tools/sdktool/sdkpersistentsettings.cpp
Normal file
@@ -0,0 +1,871 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "sdkpersistentsettings.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDataStream>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QRect>
|
||||
#include <QRegularExpression>
|
||||
#include <QStack>
|
||||
#include <QTextStream>
|
||||
#include <QXmlStreamAttributes>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define QTC_ASSERT_STRINGIFY_HELPER(x) #x
|
||||
#define QTC_ASSERT_STRINGIFY(x) QTC_ASSERT_STRINGIFY_HELPER(x)
|
||||
#define QTC_ASSERT_STRING(cond) writeAssertLocation(\
|
||||
"\"" cond"\" in " __FILE__ ":" QTC_ASSERT_STRINGIFY(__LINE__))
|
||||
|
||||
// The 'do {...} while (0)' idiom is not used for the main block here to be
|
||||
// able to use 'break' and 'continue' as 'actions'.
|
||||
|
||||
#define QTC_ASSERT(cond, action) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0)
|
||||
#define QTC_CHECK(cond) if (Q_LIKELY(cond)) {} else { QTC_ASSERT_STRING(#cond); } do {} while (0)
|
||||
#define QTC_GUARD(cond) ((Q_LIKELY(cond)) ? true : (QTC_ASSERT_STRING(#cond), false))
|
||||
|
||||
void writeAssertLocation(const char *msg)
|
||||
{
|
||||
const QByteArray time = QTime::currentTime().toString(Qt::ISODateWithMs).toLatin1();
|
||||
static bool goBoom = qEnvironmentVariableIsSet("QTC_FATAL_ASSERTS");
|
||||
if (goBoom)
|
||||
qFatal("SOFT ASSERT [%s] made fatal: %s", time.data(), msg);
|
||||
else
|
||||
qDebug("SOFT ASSERT [%s]: %s", time.data(), msg);
|
||||
}
|
||||
|
||||
static QFile::Permissions m_umask;
|
||||
|
||||
class SdkSaveFile : public QFile
|
||||
{
|
||||
public:
|
||||
explicit SdkSaveFile(const QString &filePath) : m_finalFilePath(filePath) {}
|
||||
~SdkSaveFile() override;
|
||||
|
||||
bool open(OpenMode flags = QIODevice::WriteOnly) override;
|
||||
|
||||
void rollback();
|
||||
bool commit();
|
||||
|
||||
static void initializeUmask();
|
||||
|
||||
private:
|
||||
const QString m_finalFilePath;
|
||||
std::unique_ptr<QTemporaryFile> m_tempFile;
|
||||
bool m_finalized = true;
|
||||
};
|
||||
|
||||
SdkSaveFile::~SdkSaveFile()
|
||||
{
|
||||
if (!m_finalized)
|
||||
rollback();
|
||||
}
|
||||
|
||||
bool SdkSaveFile::open(OpenMode flags)
|
||||
{
|
||||
if (m_finalFilePath.isEmpty()) {
|
||||
qWarning("Save file path empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile ofi(m_finalFilePath);
|
||||
// Check whether the existing file is writable
|
||||
if (ofi.exists() && !ofi.open(QIODevice::ReadWrite)) {
|
||||
setErrorString(ofi.errorString());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_tempFile = std::make_unique<QTemporaryFile>(m_finalFilePath);
|
||||
m_tempFile->setAutoRemove(false);
|
||||
if (!m_tempFile->open())
|
||||
return false;
|
||||
setFileName(m_tempFile->fileName());
|
||||
|
||||
if (!QFile::open(flags))
|
||||
return false;
|
||||
|
||||
m_finalized = false; // needs clean up in the end
|
||||
if (ofi.exists()) {
|
||||
setPermissions(ofi.permissions()); // Ignore errors
|
||||
} else {
|
||||
Permissions permAll = QFile::ReadOwner
|
||||
| QFile::ReadGroup
|
||||
| QFile::ReadOther
|
||||
| QFile::WriteOwner
|
||||
| QFile::WriteGroup
|
||||
| QFile::WriteOther;
|
||||
|
||||
// set permissions with respect to the current umask
|
||||
setPermissions(permAll & ~m_umask);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SdkSaveFile::rollback()
|
||||
{
|
||||
close();
|
||||
if (m_tempFile)
|
||||
m_tempFile->remove();
|
||||
m_finalized = true;
|
||||
}
|
||||
|
||||
static QString resolveSymlinks(QString current)
|
||||
{
|
||||
int links = 16;
|
||||
while (links--) {
|
||||
const QFileInfo info(current);
|
||||
if (!info.isSymLink())
|
||||
return {};
|
||||
current = info.symLinkTarget();
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
bool SdkSaveFile::commit()
|
||||
{
|
||||
QTC_ASSERT(!m_finalized && m_tempFile, return false;);
|
||||
m_finalized = true;
|
||||
|
||||
if (!flush()) {
|
||||
close();
|
||||
m_tempFile->remove();
|
||||
return false;
|
||||
}
|
||||
#ifdef Q_OS_WIN
|
||||
FlushFileBuffers(reinterpret_cast<HANDLE>(_get_osfhandle(handle())));
|
||||
#elif _POSIX_SYNCHRONIZED_IO > 0
|
||||
fdatasync(handle());
|
||||
#else
|
||||
fsync(handle());
|
||||
#endif
|
||||
close();
|
||||
m_tempFile->close();
|
||||
if (error() != NoError) {
|
||||
m_tempFile->remove();
|
||||
return false;
|
||||
}
|
||||
|
||||
QString finalFileName = resolveSymlinks(m_finalFilePath);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Release the file lock
|
||||
m_tempFile.reset();
|
||||
bool result = ReplaceFile(finalFileName.toStdWString().data(),
|
||||
fileName().toStdWString().data(),
|
||||
nullptr, REPLACEFILE_IGNORE_MERGE_ERRORS, nullptr, nullptr);
|
||||
if (!result) {
|
||||
DWORD replaceErrorCode = GetLastError();
|
||||
QString errorStr;
|
||||
if (!QFile::exists(finalFileName)) {
|
||||
// Replace failed because finalFileName does not exist, try rename.
|
||||
if (!(result = rename(finalFileName)))
|
||||
errorStr = errorString();
|
||||
} else {
|
||||
if (replaceErrorCode == ERROR_UNABLE_TO_REMOVE_REPLACED) {
|
||||
// If we do not get the rights to remove the original final file we still might try
|
||||
// to replace the file contents
|
||||
result = MoveFileEx(fileName().toStdWString().data(),
|
||||
finalFileName.toStdWString().data(),
|
||||
MOVEFILE_COPY_ALLOWED
|
||||
| MOVEFILE_REPLACE_EXISTING
|
||||
| MOVEFILE_WRITE_THROUGH);
|
||||
if (!result)
|
||||
replaceErrorCode = GetLastError();
|
||||
}
|
||||
if (!result) {
|
||||
wchar_t messageBuffer[256];
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr, replaceErrorCode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
messageBuffer, sizeof(messageBuffer), nullptr);
|
||||
errorStr = QString::fromWCharArray(messageBuffer);
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
remove();
|
||||
setErrorString(errorStr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
const QString backupName = finalFileName + '~';
|
||||
|
||||
// Back up current file.
|
||||
// If it's opened by another application, the lock follows the move.
|
||||
if (QFile::exists(finalFileName)) {
|
||||
// Kill old backup. Might be useful if creator crashed before removing backup.
|
||||
QFile::remove(backupName);
|
||||
QFile finalFile(finalFileName);
|
||||
if (!finalFile.rename(backupName)) {
|
||||
m_tempFile->remove();
|
||||
setErrorString(finalFile.errorString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
if (!m_tempFile->rename(finalFileName)) {
|
||||
// The case when someone else was able to create finalFileName after we've renamed it.
|
||||
// Higher level call may try to save this file again but here we do nothing and
|
||||
// return false while keeping the error string from last rename call.
|
||||
const QString &renameError = m_tempFile->errorString();
|
||||
m_tempFile->remove();
|
||||
setErrorString(renameError);
|
||||
QFile::rename(backupName, finalFileName); // rollback to backup if possible ...
|
||||
return false; // ... or keep the backup copy at least
|
||||
}
|
||||
|
||||
QFile::remove(backupName);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SdkSaveFile::initializeUmask()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
m_umask = QFile::WriteGroup | QFile::WriteOther;
|
||||
#else
|
||||
// Get the current process' file creation mask (umask)
|
||||
// umask() is not thread safe so this has to be done by single threaded
|
||||
// application initialization
|
||||
mode_t mask = umask(0); // get current umask
|
||||
umask(mask); // set it back
|
||||
|
||||
m_umask = ((mask & S_IRUSR) ? QFile::ReadOwner : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IWUSR) ? QFile::WriteOwner : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IXUSR) ? QFile::ExeOwner : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IRGRP) ? QFile::ReadGroup : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IWGRP) ? QFile::WriteGroup : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IXGRP) ? QFile::ExeGroup : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IROTH) ? QFile::ReadOther : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IWOTH) ? QFile::WriteOther : QFlags<QFile::Permission>())
|
||||
| ((mask & S_IXOTH) ? QFile::ExeOther : QFlags<QFile::Permission>());
|
||||
#endif
|
||||
}
|
||||
|
||||
class SdkFileSaverBase
|
||||
{
|
||||
public:
|
||||
SdkFileSaverBase() = default;
|
||||
virtual ~SdkFileSaverBase() = default;
|
||||
|
||||
QString filePath() const { return m_filePath; }
|
||||
bool hasError() const { return m_hasError; }
|
||||
QString errorString() const { return m_errorString; }
|
||||
virtual bool finalize();
|
||||
bool finalize(QString *errStr);
|
||||
|
||||
bool write(const char *data, int len);
|
||||
bool write(const QByteArray &bytes);
|
||||
bool setResult(QTextStream *stream);
|
||||
bool setResult(QDataStream *stream);
|
||||
bool setResult(QXmlStreamWriter *stream);
|
||||
bool setResult(bool ok);
|
||||
|
||||
QFile *file() { return m_file.get(); }
|
||||
|
||||
protected:
|
||||
std::unique_ptr<QFile> m_file;
|
||||
QString m_filePath;
|
||||
QString m_errorString;
|
||||
bool m_hasError = false;
|
||||
};
|
||||
|
||||
bool SdkFileSaverBase::finalize()
|
||||
{
|
||||
m_file->close();
|
||||
setResult(m_file->error() == QFile::NoError);
|
||||
m_file.reset();
|
||||
return !m_hasError;
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::finalize(QString *errStr)
|
||||
{
|
||||
if (finalize())
|
||||
return true;
|
||||
if (errStr)
|
||||
*errStr = errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::write(const char *data, int len)
|
||||
{
|
||||
if (m_hasError)
|
||||
return false;
|
||||
return setResult(m_file->write(data, len) == len);
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::write(const QByteArray &bytes)
|
||||
{
|
||||
if (m_hasError)
|
||||
return false;
|
||||
return setResult(m_file->write(bytes) == bytes.count());
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::setResult(bool ok)
|
||||
{
|
||||
if (!ok && !m_hasError) {
|
||||
if (!m_file->errorString().isEmpty()) {
|
||||
m_errorString = QString("Cannot write file %1: %2")
|
||||
.arg(m_filePath, m_file->errorString());
|
||||
} else {
|
||||
m_errorString = QString("Cannot write file %1. Disk full?")
|
||||
.arg(m_filePath);
|
||||
}
|
||||
m_hasError = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::setResult(QTextStream *stream)
|
||||
{
|
||||
stream->flush();
|
||||
return setResult(stream->status() == QTextStream::Ok);
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::setResult(QDataStream *stream)
|
||||
{
|
||||
return setResult(stream->status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
bool SdkFileSaverBase::setResult(QXmlStreamWriter *stream)
|
||||
{
|
||||
return setResult(!stream->hasError());
|
||||
}
|
||||
|
||||
// SdkFileSaver
|
||||
|
||||
class SdkFileSaver : public SdkFileSaverBase
|
||||
{
|
||||
public:
|
||||
// QIODevice::WriteOnly is implicit
|
||||
explicit SdkFileSaver(const QString &filePath, QIODevice::OpenMode mode = QIODevice::NotOpen);
|
||||
|
||||
bool finalize() override;
|
||||
|
||||
private:
|
||||
bool m_isSafe = false;
|
||||
};
|
||||
|
||||
SdkFileSaver::SdkFileSaver(const QString &filePath, QIODevice::OpenMode mode)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
// Workaround an assert in Qt -- and provide a useful error message, too:
|
||||
#ifdef Q_OS_WIN
|
||||
// Taken from: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
|
||||
static const QStringList reservedNames
|
||||
= {"CON", "PRN", "AUX", "NUL",
|
||||
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
|
||||
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
|
||||
const QString fn = QFileInfo(filePath).baseName().toUpper();
|
||||
if (reservedNames.contains(fn)) {
|
||||
m_errorString = QString("%1: Is a reserved filename on Windows. Cannot save.").arg(filePath);
|
||||
m_hasError = true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mode & (QIODevice::ReadOnly | QIODevice::Append)) {
|
||||
m_file.reset(new QFile{filePath});
|
||||
m_isSafe = false;
|
||||
} else {
|
||||
m_file.reset(new SdkSaveFile(filePath));
|
||||
m_isSafe = true;
|
||||
}
|
||||
if (!m_file->open(QIODevice::WriteOnly | mode)) {
|
||||
QString err = QFileInfo::exists(filePath) ?
|
||||
QString("Cannot overwrite file %1: %2") : QString("Cannot create file %1: %2");
|
||||
m_errorString = err.arg(filePath, m_file->errorString());
|
||||
m_hasError = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SdkFileSaver::finalize()
|
||||
{
|
||||
if (!m_isSafe)
|
||||
return SdkFileSaverBase::finalize();
|
||||
|
||||
auto sf = static_cast<SdkSaveFile *>(m_file.get());
|
||||
if (m_hasError) {
|
||||
if (sf->isOpen())
|
||||
sf->rollback();
|
||||
} else {
|
||||
setResult(sf->commit());
|
||||
}
|
||||
m_file.reset();
|
||||
return !m_hasError;
|
||||
}
|
||||
|
||||
|
||||
// Read and write rectangle in X11 resource syntax "12x12+4+3"
|
||||
static QString rectangleToString(const QRect &r)
|
||||
{
|
||||
QString result;
|
||||
QTextStream str(&result);
|
||||
str << r.width() << 'x' << r.height();
|
||||
if (r.x() >= 0)
|
||||
str << '+';
|
||||
str << r.x();
|
||||
if (r.y() >= 0)
|
||||
str << '+';
|
||||
str << r.y();
|
||||
return result;
|
||||
}
|
||||
|
||||
static QRect stringToRectangle(const QString &v)
|
||||
{
|
||||
static QRegularExpression pattern("^(\\d+)x(\\d+)([-+]\\d+)([-+]\\d+)$");
|
||||
Q_ASSERT(pattern.isValid());
|
||||
const QRegularExpressionMatch match = pattern.match(v);
|
||||
return match.hasMatch() ?
|
||||
QRect(QPoint(match.captured(3).toInt(), match.captured(4).toInt()),
|
||||
QSize(match.captured(1).toInt(), match.captured(2).toInt())) :
|
||||
QRect();
|
||||
}
|
||||
|
||||
/*!
|
||||
\class SdkPersistentSettingsReader
|
||||
|
||||
\note This is aQString based fork of Utils::PersistentSettigsReader
|
||||
|
||||
\brief The SdkPersistentSettingsReader class reads a QVariantMap of arbitrary,
|
||||
nested data structures from an XML file.
|
||||
|
||||
Handles all string-serializable simple types and QVariantList and QVariantMap. Example:
|
||||
\code
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
\endcode
|
||||
|
||||
When parsing the structure, a parse stack of ParseValueStackEntry is used for each
|
||||
<data> element. ParseValueStackEntry is a variant/union of:
|
||||
\list
|
||||
\li simple value
|
||||
\li map
|
||||
\li list
|
||||
\endlist
|
||||
|
||||
You can register string-serialize functions for custom types by registering them in the Qt Meta
|
||||
type system. Example:
|
||||
\code
|
||||
QMetaType::registerConverter(&MyCustomType::toString);
|
||||
QMetaType::registerConverter<QString, MyCustomType>(&myCustomTypeFromString);
|
||||
\endcode
|
||||
|
||||
When entering a value element ( \c <value> / \c <valuelist> , \c <valuemap> ), entry is pushed
|
||||
accordingly. When leaving the element, the QVariant-value of the entry is taken off the stack
|
||||
and added to the stack entry below (added to list or inserted into map). The first element
|
||||
of the stack is the value of the <data> element.
|
||||
|
||||
\sa SdkPersistentSettingsWriter
|
||||
*/
|
||||
|
||||
struct Context // Basic context containing element name string constants.
|
||||
{
|
||||
Context() {}
|
||||
const QString qtCreatorElement = QString("qtcreator");
|
||||
const QString dataElement = QString("data");
|
||||
const QString variableElement = QString("variable");
|
||||
const QString typeAttribute = QString("type");
|
||||
const QString valueElement = QString("value");
|
||||
const QString valueListElement = QString("valuelist");
|
||||
const QString valueMapElement = QString("valuemap");
|
||||
const QString keyAttribute = QString("key");
|
||||
};
|
||||
|
||||
struct ParseValueStackEntry
|
||||
{
|
||||
explicit ParseValueStackEntry(QVariant::Type t = QVariant::Invalid, const QString &k = QString()) : type(t), key(k) {}
|
||||
explicit ParseValueStackEntry(const QVariant &aSimpleValue, const QString &k);
|
||||
|
||||
QVariant value() const;
|
||||
void addChild(const QString &key, const QVariant &v);
|
||||
|
||||
QVariant::Type type;
|
||||
QString key;
|
||||
QVariant simpleValue;
|
||||
QVariantList listValue;
|
||||
QVariantMap mapValue;
|
||||
};
|
||||
|
||||
ParseValueStackEntry::ParseValueStackEntry(const QVariant &aSimpleValue, const QString &k) :
|
||||
type(aSimpleValue.type()), key(k), simpleValue(aSimpleValue)
|
||||
{
|
||||
QTC_ASSERT(simpleValue.isValid(), return);
|
||||
}
|
||||
|
||||
QVariant ParseValueStackEntry::value() const
|
||||
{
|
||||
switch (type) {
|
||||
case QVariant::Invalid:
|
||||
return QVariant();
|
||||
case QVariant::Map:
|
||||
return QVariant(mapValue);
|
||||
case QVariant::List:
|
||||
return QVariant(listValue);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return simpleValue;
|
||||
}
|
||||
|
||||
void ParseValueStackEntry::addChild(const QString &key, const QVariant &v)
|
||||
{
|
||||
switch (type) {
|
||||
case QVariant::Map:
|
||||
mapValue.insert(key, v);
|
||||
break;
|
||||
case QVariant::List:
|
||||
listValue.push_back(v);
|
||||
break;
|
||||
default:
|
||||
qWarning() << "ParseValueStackEntry::Internal error adding " << key << v << " to "
|
||||
<< QVariant::typeToName(type) << value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class ParseContext : public Context
|
||||
{
|
||||
public:
|
||||
QVariantMap parse(const QString &file);
|
||||
|
||||
private:
|
||||
enum Element { QtCreatorElement, DataElement, VariableElement,
|
||||
SimpleValueElement, ListValueElement, MapValueElement, UnknownElement };
|
||||
|
||||
Element element(const QStringView &r) const;
|
||||
static inline bool isValueElement(Element e)
|
||||
{ return e == SimpleValueElement || e == ListValueElement || e == MapValueElement; }
|
||||
QVariant readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const;
|
||||
|
||||
bool handleStartElement(QXmlStreamReader &r);
|
||||
bool handleEndElement(const QStringView &name);
|
||||
|
||||
static QString formatWarning(const QXmlStreamReader &r, const QString &message);
|
||||
|
||||
QStack<ParseValueStackEntry> m_valueStack;
|
||||
QVariantMap m_result;
|
||||
QString m_currentVariableName;
|
||||
};
|
||||
|
||||
static QByteArray fileContents(const QString &path)
|
||||
{
|
||||
QFile f(path);
|
||||
if (!f.exists())
|
||||
return {};
|
||||
|
||||
if (!f.open(QFile::ReadOnly))
|
||||
return {};
|
||||
|
||||
return f.readAll();
|
||||
}
|
||||
|
||||
QVariantMap ParseContext::parse(const QString &file)
|
||||
{
|
||||
QXmlStreamReader r(fileContents(file));
|
||||
|
||||
m_result.clear();
|
||||
m_currentVariableName.clear();
|
||||
|
||||
while (!r.atEnd()) {
|
||||
switch (r.readNext()) {
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (handleStartElement(r))
|
||||
return m_result;
|
||||
break;
|
||||
case QXmlStreamReader::EndElement:
|
||||
if (handleEndElement(r.name()))
|
||||
return m_result;
|
||||
break;
|
||||
case QXmlStreamReader::Invalid:
|
||||
qWarning("Error reading %s:%d: %s", qPrintable(file),
|
||||
int(r.lineNumber()), qPrintable(r.errorString()));
|
||||
return QVariantMap();
|
||||
default:
|
||||
break;
|
||||
} // switch token
|
||||
} // while (!r.atEnd())
|
||||
return m_result;
|
||||
}
|
||||
|
||||
bool ParseContext::handleStartElement(QXmlStreamReader &r)
|
||||
{
|
||||
const QStringView name = r.name();
|
||||
const Element e = element(name);
|
||||
if (e == VariableElement) {
|
||||
m_currentVariableName = r.readElementText();
|
||||
return false;
|
||||
}
|
||||
if (!ParseContext::isValueElement(e))
|
||||
return false;
|
||||
|
||||
const QXmlStreamAttributes attributes = r.attributes();
|
||||
const QString key = attributes.hasAttribute(keyAttribute) ?
|
||||
attributes.value(keyAttribute).toString() : QString();
|
||||
switch (e) {
|
||||
case SimpleValueElement: {
|
||||
// This reads away the end element, so, handle end element right here.
|
||||
const QVariant v = readSimpleValue(r, attributes);
|
||||
if (!v.isValid()) {
|
||||
qWarning() << ParseContext::formatWarning(r, QString::fromLatin1("Failed to read element \"%1\".").arg(name.toString()));
|
||||
return false;
|
||||
}
|
||||
m_valueStack.push_back(ParseValueStackEntry(v, key));
|
||||
return handleEndElement(name);
|
||||
}
|
||||
case ListValueElement:
|
||||
m_valueStack.push_back(ParseValueStackEntry(QVariant::List, key));
|
||||
break;
|
||||
case MapValueElement:
|
||||
m_valueStack.push_back(ParseValueStackEntry(QVariant::Map, key));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParseContext::handleEndElement(const QStringView &name)
|
||||
{
|
||||
const Element e = element(name);
|
||||
if (ParseContext::isValueElement(e)) {
|
||||
QTC_ASSERT(!m_valueStack.isEmpty(), return true);
|
||||
const ParseValueStackEntry top = m_valueStack.pop();
|
||||
if (m_valueStack.isEmpty()) { // Last element? -> Done with that variable.
|
||||
QTC_ASSERT(!m_currentVariableName.isEmpty(), return true);
|
||||
m_result.insert(m_currentVariableName, top.value());
|
||||
m_currentVariableName.clear();
|
||||
return false;
|
||||
}
|
||||
m_valueStack.top().addChild(top.key, top.value());
|
||||
}
|
||||
return e == QtCreatorElement;
|
||||
}
|
||||
|
||||
QString ParseContext::formatWarning(const QXmlStreamReader &r, const QString &message)
|
||||
{
|
||||
QString result = QLatin1String("Warning reading ");
|
||||
if (const QIODevice *device = r.device())
|
||||
if (const auto file = qobject_cast<const QFile *>(device))
|
||||
result += QDir::toNativeSeparators(file->fileName()) + QLatin1Char(':');
|
||||
result += QString::number(r.lineNumber());
|
||||
result += QLatin1String(": ");
|
||||
result += message;
|
||||
return result;
|
||||
}
|
||||
|
||||
ParseContext::Element ParseContext::element(const QStringView &r) const
|
||||
{
|
||||
if (r == valueElement)
|
||||
return SimpleValueElement;
|
||||
if (r == valueListElement)
|
||||
return ListValueElement;
|
||||
if (r == valueMapElement)
|
||||
return MapValueElement;
|
||||
if (r == qtCreatorElement)
|
||||
return QtCreatorElement;
|
||||
if (r == dataElement)
|
||||
return DataElement;
|
||||
if (r == variableElement)
|
||||
return VariableElement;
|
||||
return UnknownElement;
|
||||
}
|
||||
|
||||
QVariant ParseContext::readSimpleValue(QXmlStreamReader &r, const QXmlStreamAttributes &attributes) const
|
||||
{
|
||||
// Simple value
|
||||
const QStringView type = attributes.value(typeAttribute);
|
||||
const QString text = r.readElementText();
|
||||
if (type == QLatin1String("QChar")) { // Workaround: QTBUG-12345
|
||||
QTC_ASSERT(text.size() == 1, return QVariant());
|
||||
return QVariant(QChar(text.at(0)));
|
||||
}
|
||||
if (type == QLatin1String("QRect")) {
|
||||
const QRect rectangle = stringToRectangle(text);
|
||||
return rectangle.isValid() ? QVariant(rectangle) : QVariant();
|
||||
}
|
||||
QVariant value;
|
||||
value.setValue(text);
|
||||
value.convert(QMetaType::type(type.toLatin1().constData()));
|
||||
return value;
|
||||
}
|
||||
|
||||
// =================================== SdkPersistentSettingsReader
|
||||
|
||||
SdkPersistentSettingsReader::SdkPersistentSettingsReader() = default;
|
||||
|
||||
QVariant SdkPersistentSettingsReader::restoreValue(const QString &variable, const QVariant &defaultValue) const
|
||||
{
|
||||
if (m_valueMap.contains(variable))
|
||||
return m_valueMap.value(variable);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
QVariantMap SdkPersistentSettingsReader::restoreValues() const
|
||||
{
|
||||
return m_valueMap;
|
||||
}
|
||||
|
||||
bool SdkPersistentSettingsReader::load(const QString &fileName)
|
||||
{
|
||||
m_valueMap.clear();
|
||||
|
||||
if (QFileInfo(fileName).size() == 0) // skip empty files
|
||||
return false;
|
||||
|
||||
ParseContext ctx;
|
||||
m_valueMap = ctx.parse(fileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class SdkPersistentSettingsWriter
|
||||
|
||||
\note This is a fork of Utils::PersistentSettingsWriter
|
||||
|
||||
\brief The SdkPersistentSettingsWriter class serializes a QVariantMap of
|
||||
arbitrary, nested data structures to an XML file.
|
||||
\sa SdkPersistentSettingsReader
|
||||
*/
|
||||
|
||||
static void writeVariantValue(QXmlStreamWriter &w, const Context &ctx,
|
||||
const QVariant &variant, const QString &key = QString())
|
||||
{
|
||||
switch (static_cast<int>(variant.type())) {
|
||||
case static_cast<int>(QVariant::StringList):
|
||||
case static_cast<int>(QVariant::List): {
|
||||
w.writeStartElement(ctx.valueListElement);
|
||||
w.writeAttribute(ctx.typeAttribute, QLatin1String(QVariant::typeToName(QVariant::List)));
|
||||
if (!key.isEmpty())
|
||||
w.writeAttribute(ctx.keyAttribute, key);
|
||||
const QList<QVariant> list = variant.toList();
|
||||
for (const QVariant &var : list)
|
||||
writeVariantValue(w, ctx, var);
|
||||
w.writeEndElement();
|
||||
break;
|
||||
}
|
||||
case static_cast<int>(QVariant::Map): {
|
||||
w.writeStartElement(ctx.valueMapElement);
|
||||
w.writeAttribute(ctx.typeAttribute, QLatin1String(QVariant::typeToName(QVariant::Map)));
|
||||
if (!key.isEmpty())
|
||||
w.writeAttribute(ctx.keyAttribute, key);
|
||||
const QVariantMap varMap = variant.toMap();
|
||||
const QVariantMap::const_iterator cend = varMap.constEnd();
|
||||
for (QVariantMap::const_iterator i = varMap.constBegin(); i != cend; ++i)
|
||||
writeVariantValue(w, ctx, i.value(), i.key());
|
||||
w.writeEndElement();
|
||||
}
|
||||
break;
|
||||
case static_cast<int>(QMetaType::QObjectStar): // ignore QObjects!
|
||||
case static_cast<int>(QMetaType::VoidStar): // ignore void pointers!
|
||||
break;
|
||||
default:
|
||||
w.writeStartElement(ctx.valueElement);
|
||||
w.writeAttribute(ctx.typeAttribute, QLatin1String(variant.typeName()));
|
||||
if (!key.isEmpty())
|
||||
w.writeAttribute(ctx.keyAttribute, key);
|
||||
switch (variant.type()) {
|
||||
case QVariant::Rect:
|
||||
w.writeCharacters(rectangleToString(variant.toRect()));
|
||||
break;
|
||||
default:
|
||||
w.writeCharacters(variant.toString());
|
||||
break;
|
||||
}
|
||||
w.writeEndElement();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SdkPersistentSettingsWriter::SdkPersistentSettingsWriter(const QString &fileName, const QString &docType) :
|
||||
m_fileName(fileName), m_docType(docType)
|
||||
{ }
|
||||
|
||||
bool SdkPersistentSettingsWriter::save(const QVariantMap &data, QString *errorString) const
|
||||
{
|
||||
if (data == m_savedData)
|
||||
return true;
|
||||
return write(data, errorString);
|
||||
}
|
||||
|
||||
QString SdkPersistentSettingsWriter::fileName() const
|
||||
{ return m_fileName; }
|
||||
|
||||
//** * @brief Set contents of file (e.g. from data read from it). */
|
||||
void SdkPersistentSettingsWriter::setContents(const QVariantMap &data)
|
||||
{
|
||||
m_savedData = data;
|
||||
}
|
||||
|
||||
bool SdkPersistentSettingsWriter::write(const QVariantMap &data, QString *errorString) const
|
||||
{
|
||||
const QString parentDir = QDir::cleanPath(m_fileName + "/..");
|
||||
|
||||
const QFileInfo fi(parentDir);
|
||||
if (!(fi.exists() && fi.isDir() && fi.isWritable())) {
|
||||
bool res = QDir().mkpath(parentDir);
|
||||
if (!res)
|
||||
return false;
|
||||
}
|
||||
|
||||
SdkFileSaver saver(m_fileName, QIODevice::Text);
|
||||
if (!saver.hasError()) {
|
||||
const Context ctx;
|
||||
QXmlStreamWriter w(saver.file());
|
||||
w.setAutoFormatting(true);
|
||||
w.setAutoFormattingIndent(1); // Historical, used to be QDom.
|
||||
w.writeStartDocument();
|
||||
w.writeDTD(QLatin1String("<!DOCTYPE ") + m_docType + QLatin1Char('>'));
|
||||
w.writeComment(QString::fromLatin1(" Written by %1 %2, %3. ").
|
||||
arg(QCoreApplication::applicationName(),
|
||||
QCoreApplication::applicationVersion(),
|
||||
QDateTime::currentDateTime().toString(Qt::ISODate)));
|
||||
w.writeStartElement(ctx.qtCreatorElement);
|
||||
const QVariantMap::const_iterator cend = data.constEnd();
|
||||
for (QVariantMap::const_iterator it = data.constBegin(); it != cend; ++it) {
|
||||
w.writeStartElement(ctx.dataElement);
|
||||
w.writeTextElement(ctx.variableElement, it.key());
|
||||
writeVariantValue(w, ctx, it.value());
|
||||
w.writeEndElement();
|
||||
}
|
||||
w.writeEndDocument();
|
||||
|
||||
saver.setResult(&w);
|
||||
}
|
||||
bool ok = saver.finalize();
|
||||
if (ok) {
|
||||
m_savedData = data;
|
||||
} else if (errorString) {
|
||||
m_savedData.clear();
|
||||
*errorString = saver.errorString();
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
37
src/tools/sdktool/sdkpersistentsettings.h
Normal file
37
src/tools/sdktool/sdkpersistentsettings.h
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QVariant>
|
||||
|
||||
class SdkPersistentSettingsReader
|
||||
{
|
||||
public:
|
||||
SdkPersistentSettingsReader();
|
||||
QVariant restoreValue(const QString &variable, const QVariant &defaultValue = QVariant()) const;
|
||||
QVariantMap restoreValues() const;
|
||||
bool load(const QString &fileName);
|
||||
|
||||
private:
|
||||
QMap<QString, QVariant> m_valueMap;
|
||||
};
|
||||
|
||||
class SdkPersistentSettingsWriter
|
||||
{
|
||||
public:
|
||||
SdkPersistentSettingsWriter(const QString &fileName, const QString &docType);
|
||||
|
||||
bool save(const QVariantMap &data, QString *errorString) const;
|
||||
|
||||
QString fileName() const;
|
||||
|
||||
void setContents(const QVariantMap &data);
|
||||
|
||||
private:
|
||||
bool write(const QVariantMap &data, QString *errorString) const;
|
||||
|
||||
const QString m_fileName;
|
||||
const QString m_docType;
|
||||
mutable QMap<QString, QVariant> m_savedData;
|
||||
};
|
||||
@@ -85,34 +85,7 @@ QtcLibrary {
|
||||
"rmtoolchainoperation.h",
|
||||
"settings.cpp",
|
||||
"settings.h",
|
||||
"sdkpersistentsettings.cpp",
|
||||
"sdkpersistentsettings.h",
|
||||
]
|
||||
|
||||
Group {
|
||||
name: "Utils"
|
||||
prefix: libsDir + "/utils/"
|
||||
files: [
|
||||
"commandline.cpp", "commandline.h",
|
||||
"devicefileaccess.cpp", "devicefileaccess.h",
|
||||
"environment.cpp", "environment.h",
|
||||
"filepath.cpp", "filepath.h",
|
||||
"fileutils.cpp", "fileutils.h",
|
||||
"hostosinfo.cpp", "hostosinfo.h",
|
||||
"macroexpander.cpp", "macroexpander.h",
|
||||
"namevaluedictionary.cpp", "namevaluedictionary.h",
|
||||
"namevalueitem.cpp", "namevalueitem.h",
|
||||
"persistentsettings.cpp", "persistentsettings.h",
|
||||
"qtcassert.cpp", "qtcassert.h",
|
||||
"savefile.cpp", "savefile.h",
|
||||
"stringutils.cpp"
|
||||
]
|
||||
}
|
||||
Group {
|
||||
name: "Utils/macOS"
|
||||
condition: qbs.targetOS.contains("macos")
|
||||
prefix: libsDir + "/utils/"
|
||||
files: [
|
||||
"fileutils_mac.h",
|
||||
"fileutils_mac.mm",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "settings.h"
|
||||
#include "operation.h"
|
||||
|
||||
#include <app/app_version.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
|
||||
static Settings *m_instance = nullptr;
|
||||
|
||||
@@ -21,28 +21,28 @@ Settings::Settings()
|
||||
m_instance = this;
|
||||
|
||||
// autodetect sdk dir:
|
||||
sdkPath = Utils::FilePath::fromUserInput(QCoreApplication::applicationDirPath())
|
||||
.pathAppended(DATA_PATH).cleanPath()
|
||||
.pathAppended(Core::Constants::IDE_SETTINGSVARIANT_STR)
|
||||
.pathAppended(Core::Constants::IDE_ID);
|
||||
sdkPath = QDir::cleanPath(QCoreApplication::applicationDirPath()
|
||||
+ '/' + DATA_PATH
|
||||
+ '/' + Core::Constants::IDE_SETTINGSVARIANT_STR
|
||||
+ '/' + Core::Constants::IDE_ID);
|
||||
}
|
||||
|
||||
Utils::FilePath Settings::getPath(const QString &file)
|
||||
QString Settings::getPath(const QString &file)
|
||||
{
|
||||
Utils::FilePath result = sdkPath;
|
||||
QString result = sdkPath;
|
||||
const QString lowerFile = file.toLower();
|
||||
const QStringList identical = {
|
||||
"android", "cmaketools", "debuggers", "devices", "profiles", "qtversions", "toolchains", "abi"
|
||||
};
|
||||
if (lowerFile == "cmake")
|
||||
result = result.pathAppended("cmaketools");
|
||||
result += "/cmaketools";
|
||||
else if (lowerFile == "kits")
|
||||
result = result.pathAppended("profiles");
|
||||
result += "/profiles";
|
||||
else if (lowerFile == "qtversions")
|
||||
result = result.pathAppended("qtversion");
|
||||
result += "/qtversion";
|
||||
else if (identical.contains(lowerFile))
|
||||
result = result.pathAppended(lowerFile);
|
||||
result += '/' + lowerFile;
|
||||
else
|
||||
result = result.pathAppended(file); // handle arbitrary file names not known yet
|
||||
return result.stringAppended(".xml");
|
||||
result += '/' + file; // handle arbitrary file names not known yet
|
||||
return result += ".xml";
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <QString>
|
||||
|
||||
class Operation;
|
||||
|
||||
@@ -13,8 +13,8 @@ public:
|
||||
Settings();
|
||||
static Settings *instance();
|
||||
|
||||
Utils::FilePath getPath(const QString &file);
|
||||
QString getPath(const QString &file);
|
||||
|
||||
Utils::FilePath sdkPath;
|
||||
QString sdkPath;
|
||||
Operation *operation = nullptr;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ Project {
|
||||
"buildoutputparser/buildoutputparser.qbs",
|
||||
"cplusplustools.qbs",
|
||||
"disclaim/disclaim.qbs",
|
||||
"process_stub/process_stub.qbs",
|
||||
"processlauncher/processlauncher.qbs",
|
||||
"qml2puppet/qml2puppet.qbs",
|
||||
"qtcdebugger/qtcdebugger.qbs",
|
||||
|
||||
Reference in New Issue
Block a user