Merge branch 'master' into path_custom_source

This commit is contained in:
Morgan 'ARR\!' Allen
2023-03-29 20:50:07 -07:00
67 changed files with 1431 additions and 1497 deletions

View File

@@ -49,6 +49,7 @@
<file>icons/Draft_Join.svg</file>
<file>icons/Draft_Label.svg</file>
<file>icons/Draft_Layer.svg</file>
<file>icons/Draft_LayerManager.svg</file>
<file>icons/Draft_Line.svg</file>
<file>icons/Draft_LinkArray.svg</file>
<file>icons/Draft_Lock.svg</file>
@@ -191,5 +192,6 @@
<file>ui/dialog_AnnotationStyleEditor.ui</file>
<file>ui/TaskPanel_SetStyle.ui</file>
<file>ui/dialogHatch.ui</file>
<file>ui/dialogLayers.ui</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,515 @@
<?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="48.000000px"
height="48.000000px"
id="svg249"
sodipodi:version="0.32"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="BIM_Layers.svg"
inkscape:export-filename="/home/jimmac/gfx/novell/pdes/trunk/docs/BIGmime-text.png"
inkscape:export-xdpi="240.00000"
inkscape:export-ydpi="240.00000"
version="1.1">
<defs
id="defs3">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5060"
id="radialGradient5031"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<linearGradient
inkscape:collect="always"
id="linearGradient5060">
<stop
style="stop-color:black;stop-opacity:1;"
offset="0"
id="stop5062" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5064" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5060"
id="radialGradient5029"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<linearGradient
id="linearGradient5048">
<stop
style="stop-color:black;stop-opacity:0;"
offset="0"
id="stop5050" />
<stop
id="stop5056"
offset="0.5"
style="stop-color:black;stop-opacity:1;" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5052" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5048"
id="linearGradient5027"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
x1="302.85715"
y1="366.64789"
x2="302.85715"
y2="609.50507" />
<linearGradient
inkscape:collect="always"
id="linearGradient4542">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop4544" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop4546" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient4542"
id="radialGradient4548"
cx="24.306795"
cy="42.07798"
fx="24.306795"
fy="42.07798"
r="15.821514"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.284916,-6.310056e-16,30.08928)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient15662">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop15664" />
<stop
style="stop-color:#f8f8f8;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop15666" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
fy="64.5679"
fx="20.8921"
r="5.257"
cy="64.5679"
cx="20.8921"
id="aigrd3">
<stop
id="stop15573"
style="stop-color:#F0F0F0"
offset="0" />
<stop
id="stop15575"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
offset="1.0000000" />
</radialGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
fy="114.5684"
fx="20.8921"
r="5.256"
cy="114.5684"
cx="20.8921"
id="aigrd2">
<stop
id="stop15566"
style="stop-color:#F0F0F0"
offset="0" />
<stop
id="stop15568"
style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
offset="1.0000000" />
</radialGradient>
<linearGradient
id="linearGradient269">
<stop
style="stop-color:#a3a3a3;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop270" />
<stop
style="stop-color:#4c4c4c;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop271" />
</linearGradient>
<linearGradient
id="linearGradient259">
<stop
style="stop-color:#fafafa;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop260" />
<stop
style="stop-color:#bbbbbb;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop261" />
</linearGradient>
<linearGradient
id="linearGradient12512">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop12513" />
<stop
style="stop-color:#fff520;stop-opacity:0.89108908;"
offset="0.50000000"
id="stop12517" />
<stop
style="stop-color:#fff300;stop-opacity:0.0000000;"
offset="1.0000000"
id="stop12514" />
</linearGradient>
<radialGradient
r="37.751713"
fy="3.7561285"
fx="8.8244190"
cy="3.7561285"
cx="8.8244190"
gradientTransform="matrix(0.968273,0.000000,0.000000,1.032767,3.353553,0.646447)"
gradientUnits="userSpaceOnUse"
id="radialGradient15656"
xlink:href="#linearGradient269"
inkscape:collect="always" />
<radialGradient
r="86.708450"
fy="35.736916"
fx="33.966679"
cy="35.736916"
cx="33.966679"
gradientTransform="scale(0.960493,1.041132)"
gradientUnits="userSpaceOnUse"
id="radialGradient15658"
xlink:href="#linearGradient259"
inkscape:collect="always" />
<radialGradient
r="38.158695"
fy="7.2678967"
fx="8.1435566"
cy="7.2678967"
cx="8.1435566"
gradientTransform="matrix(0.968273,0.000000,0.000000,1.032767,3.353553,0.646447)"
gradientUnits="userSpaceOnUse"
id="radialGradient15668"
xlink:href="#linearGradient15662"
inkscape:collect="always" />
<radialGradient
inkscape:collect="always"
xlink:href="#aigrd2"
id="radialGradient2283"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.229703,0.000000,0.000000,0.229703,4.613529,3.979808)"
cx="20.8921"
cy="114.5684"
fx="20.8921"
fy="114.5684"
r="5.256" />
<radialGradient
inkscape:collect="always"
xlink:href="#aigrd3"
id="radialGradient2285"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.229703,0.000000,0.000000,0.229703,4.613529,3.979808)"
cx="20.8921"
cy="64.5679"
fx="20.8921"
fy="64.5679"
r="5.257" />
<linearGradient
id="linearGradient3815"
inkscape:collect="always">
<stop
id="stop3817"
offset="0"
style="stop-color:#d3d7cf;stop-opacity:1;" />
<stop
id="stop3819"
offset="1"
style="stop-color:#ffffff;stop-opacity:1" />
</linearGradient>
<linearGradient
gradientTransform="translate(-0.02151317,-0.91811256)"
gradientUnits="userSpaceOnUse"
y2="-1.3815211"
x2="25.928942"
y1="19.086002"
x1="53.257175"
id="linearGradient3805"
xlink:href="#linearGradient3815"
inkscape:collect="always" />
<linearGradient
gradientTransform="translate(0.75600263,0.0412295)"
gradientUnits="userSpaceOnUse"
y2="12.022611"
x2="36.843666"
y1="27.953379"
x1="61.719494"
id="linearGradient3813"
xlink:href="#linearGradient3815"
inkscape:collect="always" />
<linearGradient
gradientTransform="translate(-0.18895427,-1.1237431)"
gradientUnits="userSpaceOnUse"
y2="23.542751"
x2="48.388607"
y1="43.419685"
x1="74.313408"
id="linearGradient3821"
xlink:href="#linearGradient3815"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="0.32941176"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="93.761718"
inkscape:cy="-13.65303"
inkscape:current-layer="layer4"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1920"
inkscape:window-height="1051"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:showpageshadow="false"
inkscape:window-maximized="1" />
<metadata
id="metadata4">
<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:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz</dc:source>
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Attribution" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="Shadow"
id="layer6"
inkscape:groupmode="layer">
<g
style="display:inline"
id="g5022"
transform="matrix(2.165152e-2,0,0,1.485743e-2,43.0076,42.68539)">
<rect
y="-150.69685"
x="-1559.2523"
height="478.35718"
width="1339.6335"
id="rect4173"
style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
sodipodi:nodetypes="cccc"
id="path5058"
d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
id="path5018"
sodipodi:nodetypes="cccc" />
</g>
</g>
<g
id="layer1"
inkscape:label="Base"
inkscape:groupmode="layer"
style="display:inline">
<rect
ry="1.1490486"
y="3.6464462"
x="6.6035528"
height="40.920494"
width="34.875000"
id="rect15391"
style="color:#000000;fill:url(#radialGradient15658);fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
<rect
rx="0.14904857"
ry="0.14904857"
y="4.5839462"
x="7.6660538"
height="38.946384"
width="32.775887"
id="rect15660"
style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
<g
id="g2270"
transform="translate(0.646447,-3.798933e-2)">
<g
transform="matrix(0.229703,0.000000,0.000000,0.229703,4.967081,4.244972)"
style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4.0000000"
id="g1440">
<radialGradient
gradientUnits="userSpaceOnUse"
fy="114.56840"
fx="20.892099"
r="5.2560000"
cy="114.56840"
cx="20.892099"
id="radialGradient1442">
<stop
id="stop1444"
style="stop-color:#F0F0F0"
offset="0" />
<stop
id="stop1446"
style="stop-color:#474747"
offset="1" />
</radialGradient>
<path
id="path1448"
d="M 23.428000,113.07000 C 23.428000,115.04300 21.828000,116.64200 19.855000,116.64200 C 17.881000,116.64200 16.282000,115.04200 16.282000,113.07000 C 16.282000,111.09600 17.882000,109.49700 19.855000,109.49700 C 21.828000,109.49700 23.428000,111.09700 23.428000,113.07000 z "
style="stroke:none" />
<radialGradient
gradientUnits="userSpaceOnUse"
fy="64.567902"
fx="20.892099"
r="5.2570000"
cy="64.567902"
cx="20.892099"
id="radialGradient1450">
<stop
id="stop1452"
style="stop-color:#F0F0F0"
offset="0" />
<stop
id="stop1454"
style="stop-color:#474747"
offset="1" />
</radialGradient>
<path
id="path1456"
d="M 23.428000,63.070000 C 23.428000,65.043000 21.828000,66.643000 19.855000,66.643000 C 17.881000,66.643000 16.282000,65.043000 16.282000,63.070000 C 16.282000,61.096000 17.882000,59.497000 19.855000,59.497000 C 21.828000,59.497000 23.428000,61.097000 23.428000,63.070000 z "
style="stroke:none" />
</g>
<path
id="path15570"
d="M 9.9950109,29.952326 C 9.9950109,30.405530 9.6274861,30.772825 9.1742821,30.772825 C 8.7208483,30.772825 8.3535532,30.405301 8.3535532,29.952326 C 8.3535532,29.498892 8.7210780,29.131597 9.1742821,29.131597 C 9.6274861,29.131597 9.9950109,29.499122 9.9950109,29.952326 z "
style="fill:url(#radialGradient2283);fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000" />
<path
id="path15577"
d="M 9.9950109,18.467176 C 9.9950109,18.920380 9.6274861,19.287905 9.1742821,19.287905 C 8.7208483,19.287905 8.3535532,18.920380 8.3535532,18.467176 C 8.3535532,18.013742 8.7210780,17.646447 9.1742821,17.646447 C 9.6274861,17.646447 9.9950109,18.013972 9.9950109,18.467176 z "
style="fill:url(#radialGradient2285);fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000" />
</g>
<path
sodipodi:nodetypes="cc"
id="path15672"
d="M 11.505723,5.4942766 L 11.505723,43.400869"
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.98855311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.017543854" />
<path
sodipodi:nodetypes="cc"
id="path15674"
d="M 12.500000,5.0205154 L 12.500000,43.038228"
style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.20467831" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="new"
style="display:inline">
<g
inkscape:label="Layer 1"
id="layer1-6"
transform="matrix(0.45072343,0,0,0.45072343,9.6052107,9.3385922)"
style="stroke-width:2.53389549;stroke-miterlimit:4;stroke-dasharray:none">
<rect
transform="matrix(0.92408158,0.38219528,-0.75246174,0.65863596,0,0)"
y="16.492231"
x="40.359722"
height="27.016869"
width="39.045357"
id="rect2993"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3821);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:7.0861426;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="rect2993-0-9-3-7"
d="M 25.329927,28.679638 57.173418,41.866954 40.234042,56.653163 8.3211848,43.465847 Z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:2.53389549;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<rect
transform="matrix(0.92408158,0.38219528,-0.75246174,0.65863596,0,0)"
y="6.2172832"
x="31.989382"
height="27.016869"
width="39.045357"
id="rect2993-0"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3813);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:7.0861426;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="rect2993-0-9-3-6"
d="M 25.30824,18.773895 57.151731,31.961211 40.212355,46.74742 8.2994962,33.560104 Z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:2.53389549;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<rect
transform="matrix(0.92408158,0.38219528,-0.75246174,0.65863596,6.510896e-8,5.0104617e-8)"
y="-6.1819811"
x="21.896566"
height="27.016869"
width="39.045357"
id="rect2993-0-9"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient3805);fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:7.0861426;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="rect2993-0-9-3"
d="M 25.281278,6.6563352 57.124769,19.843651 40.185393,34.62986 8.2725348,21.442544 Z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:2.53389549;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>667</width>
<height>320</height>
</rect>
</property>
<property name="windowTitle">
<string>Layers manager</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeView" name="tree">
<property name="sortingEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="buttonNew">
<property name="text">
<string>New</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonDelete">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSelectAll">
<property name="text">
<string>Select all</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonToggle">
<property name="text">
<string>Toggle on/off</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonIsolate">
<property name="text">
<string>Isolate</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonOK">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -148,7 +148,7 @@ class DraftTool:
if utils.get_param("showPlaneTracker", False):
self.planetrack = trackers.PlaneTracker()
if hasattr(Gui, "Snapper"):
Gui.Snapper.setTrackers()
Gui.Snapper.setTrackers(tool=True)
_msg("{}".format(16*"-"))
_msg("GuiCommand: {}".format(self.featureName))

View File

@@ -66,7 +66,7 @@ class ToggleGrid(gui_base.GuiCommandSimplest):
super(ToggleGrid, self).Activated()
if hasattr(Gui, "Snapper"):
Gui.Snapper.setTrackers()
Gui.Snapper.setTrackers(tool=True)
if Gui.Snapper.grid:
if Gui.Snapper.grid.Visible:
Gui.Snapper.grid.off()

View File

@@ -30,7 +30,10 @@
# @{
from PySide.QtCore import QT_TRANSLATE_NOOP
import os
import FreeCAD
import FreeCADGui as Gui
import Draft
import Draft_rc
import draftguitools.gui_base as gui_base
@@ -40,6 +43,18 @@ from draftutils.translate import translate
bool(Draft_rc.__name__)
def getColorIcon(color):
"returns a QtGui.QIcon from a color 3-float tuple"
from PySide import QtCore,QtGui
c = QtGui.QColor(int(color[0]*255),int(color[1]*255),int(color[2]*255))
im = QtGui.QImage(48,48,QtGui.QImage.Format_ARGB32)
im.fill(c)
px = QtGui.QPixmap.fromImage(im)
return QtGui.QIcon(px)
class Layer(gui_base.GuiCommandSimplest):
"""GuiCommand to create a Layer object in the document."""
@@ -66,6 +81,435 @@ class Layer(gui_base.GuiCommandSimplest):
self.doc.commitTransaction()
class LayerManager:
"""GuiCommand that displays a Layers manager dialog"""
def GetResources(self):
return {'Pixmap' : 'Draft_LayerManager',
'MenuText': QT_TRANSLATE_NOOP("Draft_LayerManager", "Manage layers..."),
'ToolTip' : QT_TRANSLATE_NOOP("Draft_LayerManager", "Set/modify the different layers of this document")}
def Activated(self):
from PySide import QtCore, QtGui
# store changes to be committed
self.deleteList = []
# create the dialog
self.dialog = Gui.PySideUic.loadUi(":/ui/dialogLayers.ui")
# set nice icons
self.dialog.setWindowIcon(QtGui.QIcon(":/icons/Draft_Layer.svg"))
self.dialog.buttonNew.setIcon(QtGui.QIcon(":/icons/document-new.svg"))
self.dialog.buttonDelete.setIcon(QtGui.QIcon(":/icons/delete.svg"))
self.dialog.buttonSelectAll.setIcon(QtGui.QIcon(":/icons/edit-select-all.svg"))
self.dialog.buttonToggle.setIcon(QtGui.QIcon(":/icons/dagViewVisible.svg"))
self.dialog.buttonIsolate.setIcon(QtGui.QIcon(":/icons/view-refresh.svg"))
self.dialog.buttonCancel.setIcon(QtGui.QIcon(":/icons/edit_Cancel.svg"))
self.dialog.buttonOK.setIcon(QtGui.QIcon(":/icons/edit_OK.svg"))
# restore window geometry from stored state
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
w = pref.GetInt("LayersManagerWidth",640)
h = pref.GetInt("LayersManagerHeight",320)
self.dialog.resize(w,h)
# center the dialog over FreeCAD window
mw = Gui.getMainWindow()
self.dialog.move(mw.frameGeometry().topLeft() + mw.rect().center() - self.dialog.rect().center())
# connect signals/slots
self.dialog.buttonNew.clicked.connect(self.addItem)
self.dialog.buttonDelete.clicked.connect(self.onDelete)
self.dialog.buttonSelectAll.clicked.connect(self.dialog.tree.selectAll)
self.dialog.buttonToggle.clicked.connect(self.onToggle)
self.dialog.buttonCancel.clicked.connect(self.dialog.reject)
self.dialog.buttonIsolate.clicked.connect(self.onIsolate)
self.dialog.buttonOK.clicked.connect(self.accept)
self.dialog.rejected.connect(self.reject)
# set the model up
self.model = QtGui.QStandardItemModel()
self.dialog.tree.setModel(self.model)
self.dialog.tree.setUniformRowHeights(True)
self.dialog.tree.setItemDelegate(Layers_Delegate())
self.dialog.tree.setItemsExpandable(False)
self.dialog.tree.setRootIsDecorated(False) # removes spacing in first column
self.dialog.tree.setSelectionMode(QtGui.QTreeView.ExtendedSelection) # allow to select many
# fill the tree view
self.update()
# rock 'n roll!!!
self.dialog.exec_()
def accept(self):
"when OK button is pressed"
changed = False
# delete layers
for name in self.deleteList:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
FreeCAD.ActiveDocument.removeObject(name)
# apply changes
for row in range(self.model.rowCount()):
# get or create layer
name = self.model.item(row,1).toolTip()
obj = None
if name:
obj = FreeCAD.ActiveDocument.getObject(name)
if not obj:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj = Draft.make_layer()
# visibility
checked = True if self.model.item(row,0).checkState() == QtCore.Qt.Checked else False
if checked != obj.ViewObject.Visibility:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.Visibility = checked
# label
label = self.model.item(row,1).text()
if label:
if obj.Label != label:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.Label = label
# line width
width = self.model.item(row,2).data(QtCore.Qt.DisplayRole)
if width:
if obj.ViewObject.LineWidth != width:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.LineWidth = width
# draw style
style = self.model.item(row,3).text()
if style:
if obj.ViewObject.DrawStyle != style:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.DrawStyle = style
# line color
color = self.model.item(row,4).data(QtCore.Qt.UserRole)
if color:
if obj.ViewObject.LineColor[3:] != color:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.LineColor = color
# shape color
color = self.model.item(row,5).data(QtCore.Qt.UserRole)
if color:
if obj.ViewObject.ShapeColor[3:] != color:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.ShapeColor = color
# transparency
transparency = self.model.item(row,6).data(QtCore.Qt.DisplayRole)
if transparency:
if obj.ViewObject.Transparency != transparency:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.Transparency = transparency
# line print color
color = self.model.item(row,7).data(QtCore.Qt.UserRole)
if color:
if not "LinePrintColor" in obj.ViewObject.PropertiesList:
if hasattr(obj.ViewObject.Proxy,"set_properties"):
obj.ViewObject.Proxy.set_properties(obj.ViewObject)
if "LinePrintColor" in obj.ViewObject.PropertiesList:
if obj.ViewObject.LinePrintColor[3:] != color:
if not changed:
FreeCAD.ActiveDocument.openTransaction("Layers change")
changed = True
obj.ViewObject.LinePrintColor = color
# recompute
if changed:
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
# exit
self.dialog.reject()
def reject(self):
"when Cancel button is pressed or dialog is closed"
# save dialog size
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
pref.SetInt("LayersManagerWidth",self.dialog.width())
pref.SetInt("LayersManagerHeight",self.dialog.height())
return True
def update(self):
"rebuild the model from document contents"
self.model.clear()
# set header
self.model.setHorizontalHeaderLabels([translate("Draft","On"),
translate("Draft","Name"),
translate("Draft","Line width"),
translate("Draft","Draw style"),
translate("Draft","Line color"),
translate("Draft","Face color"),
translate("Draft","Transparency"),
translate("Draft","Line print color")])
self.dialog.tree.header().setDefaultSectionSize(72)
self.dialog.tree.setColumnWidth(0,32) # on/off column
self.dialog.tree.setColumnWidth(1,128) # name column
# populate
objs = [obj for obj in FreeCAD.ActiveDocument.Objects if Draft.getType(obj) == "Layer"]
objs.sort(key=lambda o:o.Label)
for obj in objs:
self.addItem(obj)
def addItem(self,obj=None):
"adds a row to the model"
from PySide import QtCore, QtGui
# create row with default values
onItem = QtGui.QStandardItem()
onItem.setCheckable(True)
onItem.setCheckState(QtCore.Qt.Checked)
nameItem = QtGui.QStandardItem(translate("Draft","New Layer"))
widthItem = QtGui.QStandardItem()
widthItem.setData(self.getPref("DefaultShapeLineWidth",2,"Integer"),QtCore.Qt.DisplayRole)
styleItem = QtGui.QStandardItem("Solid")
lineColorItem = QtGui.QStandardItem()
lineColorItem.setData(self.getPref("DefaultShapeLineColor",421075455),QtCore.Qt.UserRole)
shapeColorItem = QtGui.QStandardItem()
shapeColorItem.setData(self.getPref("DefaultShapeColor",3435973887),QtCore.Qt.UserRole)
transparencyItem = QtGui.QStandardItem()
transparencyItem.setData(0,QtCore.Qt.DisplayRole)
linePrintColorItem = QtGui.QStandardItem()
linePrintColorItem.setData(self.getPref("DefaultPrintColor",0),QtCore.Qt.UserRole)
# populate with object data
if obj:
onItem.setCheckState(QtCore.Qt.Checked if obj.ViewObject.Visibility else QtCore.Qt.Unchecked)
nameItem.setText(obj.Label)
nameItem.setToolTip(obj.Name)
widthItem.setData(obj.ViewObject.LineWidth,QtCore.Qt.DisplayRole)
styleItem.setText(obj.ViewObject.DrawStyle)
lineColorItem.setData(obj.ViewObject.LineColor[:3],QtCore.Qt.UserRole)
shapeColorItem.setData(obj.ViewObject.ShapeColor[:3],QtCore.Qt.UserRole)
transparencyItem.setData(obj.ViewObject.Transparency,QtCore.Qt.DisplayRole)
if hasattr(obj.ViewObject,"LinePrintColor"):
linePrintColorItem.setData(obj.ViewObject.LinePrintColor[:3],QtCore.Qt.UserRole)
lineColorItem.setIcon(getColorIcon(lineColorItem.data(QtCore.Qt.UserRole)))
shapeColorItem.setIcon(getColorIcon(shapeColorItem.data(QtCore.Qt.UserRole)))
linePrintColorItem.setIcon(getColorIcon(linePrintColorItem.data(QtCore.Qt.UserRole)))
# append row
self.model.appendRow([onItem,
nameItem,
widthItem,
styleItem,
lineColorItem,
shapeColorItem,
transparencyItem,
linePrintColorItem])
def getPref(self,value,default,valuetype="Unsigned"):
"retrieves a view pref value"
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View")
if valuetype == "Unsigned":
c = p.GetUnsigned(value,default)
r = float((c>>24)&0xFF)/255.0
g = float((c>>16)&0xFF)/255.0
b = float((c>>8)&0xFF)/255.0
return (r,g,b,)
elif valuetype == "Integer":
return p.GetInt(value,default)
def onDelete(self):
"delete selected rows"
rows = []
for index in self.dialog.tree.selectedIndexes():
if not index.row() in rows:
rows.append(index.row())
# append layer name to the delete list
if index.column() == 1:
name = self.model.itemFromIndex(index).toolTip()
if name:
if not name in self.deleteList:
self.deleteList.append(name)
# delete rows starting from the lowest, to not alter row indexes while deleting
rows.sort()
rows.reverse()
for row in rows:
self.model.takeRow(row)
def onToggle(self):
"toggle selected layers on/off"
from PySide import QtCore, QtGui
state = None
for index in self.dialog.tree.selectedIndexes():
if index.column() == 0:
# get state from first selected row
if state is None:
if self.model.itemFromIndex(index).checkState() == QtCore.Qt.Checked:
state = QtCore.Qt.Unchecked
else:
state = QtCore.Qt.Checked
self.model.itemFromIndex(index).setCheckState(state)
def onIsolate(self):
"isolates the selected layers (turns all the others off"
from PySide import QtCore, QtGui
onrows = []
for index in self.dialog.tree.selectedIndexes():
if not index.row() in onrows:
onrows.append(index.row())
for row in range(self.model.rowCount()):
if not row in onrows:
self.model.item(row,0).setCheckState(QtCore.Qt.Unchecked)
if FreeCAD.GuiUp:
from PySide import QtCore, QtGui
class Layers_Delegate(QtGui.QStyledItemDelegate):
"model delegate"
def __init__(self, parent=None, *args):
QtGui.QStyledItemDelegate.__init__(self, parent, *args)
# setEditorData() is triggered several times.
# But we want to show the color dialog only the first time
self.first = True
def createEditor(self,parent,option,index):
if index.column() == 0: # Layer on/off
editor = QtGui.QCheckBox(parent)
if index.column() == 1: # Layer name
editor = QtGui.QLineEdit(parent)
elif index.column() == 2: # Line width
editor = QtGui.QSpinBox(parent)
editor.setMaximum(99)
elif index.column() == 3: # Line style
editor = QtGui.QComboBox(parent)
editor.addItems(["Solid","Dashed","Dotted","Dashdot"])
elif index.column() == 4: # Line color
editor = QtGui.QLineEdit(parent)
self.first = True
elif index.column() == 5: # Shape color
editor = QtGui.QLineEdit(parent)
self.first = True
elif index.column() == 6: # Transparency
editor = QtGui.QSpinBox(parent)
editor.setMaximum(100)
elif index.column() == 7: # Line print color
editor = QtGui.QLineEdit(parent)
self.first = True
return editor
def setEditorData(self, editor, index):
if index.column() == 0: # Layer on/off
editor.setChecked(index.data())
elif index.column() == 1: # Layer name
editor.setText(index.data())
elif index.column() == 2: # Line width
editor.setValue(index.data())
elif index.column() == 3: # Line style
editor.setCurrentIndex(["Solid","Dashed","Dotted","Dashdot"].index(index.data()))
elif index.column() == 4: # Line color
editor.setText(str(index.data(QtCore.Qt.UserRole)))
if self.first:
c = index.data(QtCore.Qt.UserRole)
color = QtGui.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255)))
editor.setText(str(color.getRgbF()))
self.first = False
elif index.column() == 5: # Shape color
editor.setText(str(index.data(QtCore.Qt.UserRole)))
if self.first:
c = index.data(QtCore.Qt.UserRole)
color = QtGui.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255)))
editor.setText(str(color.getRgbF()))
self.first = False
elif index.column() == 6: # Transparency
editor.setValue(index.data())
elif index.column() == 7: # Line print color
editor.setText(str(index.data(QtCore.Qt.UserRole)))
if self.first:
c = index.data(QtCore.Qt.UserRole)
color = QtGui.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255)))
editor.setText(str(color.getRgbF()))
self.first = False
def setModelData(self, editor, model, index):
if index.column() == 0: # Layer on/off
model.setData(index,editor.isChecked())
elif index.column() == 1: # Layer name
model.setData(index,editor.text())
elif index.column() == 2: # Line width
model.setData(index,editor.value())
elif index.column() == 3: # Line style
model.setData(index,["Solid","Dashed","Dotted","Dashdot"][editor.currentIndex()])
elif index.column() == 4: # Line color
model.setData(index,eval(editor.text()),QtCore.Qt.UserRole)
model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text())))
elif index.column() == 5: # Shape color
model.setData(index,eval(editor.text()),QtCore.Qt.UserRole)
model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text())))
elif index.column() == 6: # Transparency
model.setData(index,editor.value())
elif index.column() == 7: # Line prin color
model.setData(index,eval(editor.text()),QtCore.Qt.UserRole)
model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text())))
Gui.addCommand('Draft_Layer', Layer())
Gui.addCommand('Draft_LayerManager', LayerManager())
## @}

View File

@@ -139,7 +139,7 @@ class Line(gui_base_original.Creator):
if self.oldWP:
App.DraftWorkingPlane.setFromParameters(self.oldWP)
if hasattr(Gui, "Snapper"):
Gui.Snapper.setGrid()
Gui.Snapper.setGrid(tool=True)
Gui.Snapper.restack()
self.oldWP = None

View File

@@ -1594,15 +1594,15 @@ class Snapper:
self.toolbar.toggleViewAction().setVisible(False)
def setGrid(self):
def setGrid(self, tool=False):
"""Set the grid, if visible."""
self.setTrackers()
if self.grid and (not self.forceGridOff):
if self.grid.Visible:
self.grid.set()
self.grid.set(tool)
def setTrackers(self):
def setTrackers(self, tool=False):
"""Set the trackers."""
v = Draft.get3DView()
if v and (v != self.activeview):
@@ -1620,7 +1620,10 @@ class Snapper:
else:
if Draft.getParam("grid", True):
self.grid = trackers.gridTracker()
self.grid.on()
if Draft.getParam("alwaysShowGrid", True) or tool:
self.grid.on()
else:
self.grid.off()
else:
self.grid = None
self.tracker = trackers.snapTracker()
@@ -1651,7 +1654,7 @@ class Snapper:
self.activeview = v
if self.grid and (not self.forceGridOff):
self.grid.set()
self.grid.set(tool)
def addHoldPoint(self):

View File

@@ -1216,7 +1216,7 @@ class gridTracker(Tracker):
self.numlines = Draft.getParam("gridSize", 100)
self.update()
def set(self):
def set(self,tool=False):
"""Move and rotate the grid according to the current working plane."""
self.reset()
Q = FreeCAD.DraftWorkingPlane.getRotation().Rotation.Q
@@ -1225,7 +1225,8 @@ class gridTracker(Tracker):
self.trans.translation.setValue([P.x, P.y, P.z])
self.displayHumanFigure()
self.setAxesColor()
self.on()
if tool:
self.on()
def getClosestNode(self, point):
"""Return the closest node from the given point."""

View File

@@ -112,6 +112,7 @@ def get_draft_utility_commands_menu():
"Draft_ApplyStyle",
"Separator",
"Draft_Layer",
"Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",
@@ -130,7 +131,7 @@ def get_draft_utility_commands_menu():
def get_draft_utility_commands_toolbar():
"""Return the utility commands list for the toolbar."""
return ["Draft_Layer",
return ["Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",

View File

@@ -31,6 +31,7 @@
# include <Inventor/nodes/SoSeparator.h>
#endif
#include <App/Document.h>
#include <App/MaterialObject.h>
#include <App/TextDocument.h>
#include <Gui/ActionFunction.h>
@@ -38,6 +39,8 @@
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/MainWindow.h>
#include <Gui/Selection.h>
#include <Gui/SelectionObject.h>
#include <Mod/Fem/App/FemAnalysis.h>
#include <Mod/Fem/App/FemConstraint.h>
#include <Mod/Fem/App/FemMeshObject.h>
@@ -251,15 +254,40 @@ void ViewProviderFemAnalysis::dropObject(App::DocumentObject *obj)
bool ViewProviderFemAnalysis::onDelete(const std::vector<std::string> &)
{
// warn the user if the object has childs
// warn the user if the object has unselected children
auto objs = claimChildren();
return checkSelectedChildren(objs, this->getDocument(), "analysis");
}
bool ViewProviderFemAnalysis::checkSelectedChildren(const std::vector<App::DocumentObject*> objs,
Gui::Document* docGui, std::string objectName)
{
// warn the user if the object has unselected children
if (!objs.empty()) {
// check if all children are in the selection
bool found = false;
auto selectionList = Gui::Selection().getSelectionEx(docGui->getDocument()->getName());
for (auto child : objs) {
found = false;
for (Gui::SelectionObject selection : selectionList) {
if (std::string(child->getNameInDocument())
== std::string(selection.getFeatName())) {
found = true;
break;
}
}
if (!found)
break;
}
if (found)// all children are selected too
return true;
// generate dialog
QString bodyMessage;
QTextStream bodyMessageStream(&bodyMessage);
bodyMessageStream << qApp->translate("Std_Delete",
"The analysis is not empty, therefore the\nfollowing referencing objects might be lost:");
("The " + objectName + " is not empty, therefore the\nfollowing "
"referencing objects might be lost:").c_str());
bodyMessageStream << '\n';
for (auto ObjIterator : objs)
bodyMessageStream << '\n' << QString::fromUtf8(ObjIterator->Label.getValue());

View File

@@ -52,10 +52,10 @@ class FemGuiExport ViewProviderFemAnalysis : public Gui::ViewProviderDocumentObj
PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderAnalysis);
public:
/// constructor.
/// constructor
ViewProviderFemAnalysis();
/// destructor.
/// destructor
~ViewProviderFemAnalysis() override;
void attach(App::DocumentObject*) override;
@@ -63,17 +63,19 @@ public:
std::vector<App::DocumentObject*> claimChildren()const override;
// handling when object is deleted
/// handling when object is deleted
bool onDelete(const std::vector<std::string>&) override;
/// Asks the view provider if the given object can be deleted.
/// warning on deletion when there are children
static bool checkSelectedChildren(const std::vector<App::DocumentObject*> objs,
Gui::Document* docGui, std::string objectName);
/// asks the view provider if the given object can be deleted
bool canDelete(App::DocumentObject* obj) const override;
//virtual std::vector<App::DocumentObject*> claimChildren3D(void)const;
void setupContextMenu(QMenu*, QObject*, const char*) override;
/// A list of all possible display modes
/// list of all possible display modes
std::vector<std::string> getDisplayModes() const override;
// shows solid in the tree
/// shows solid in the tree
bool isShow() const override {
return Visibility.getValue();
}

View File

@@ -56,6 +56,7 @@
#include "ViewProviderFemPostFunction.h"
#include "FemSettings.h"
#include "TaskPostBoxes.h"
#include "ViewProviderAnalysis.h"
#include "ui_BoxWidget.h"
#include "ui_CylinderWidget.h"
@@ -133,32 +134,10 @@ void ViewProviderFemPostFunctionProvider::updateSize()
bool ViewProviderFemPostFunctionProvider::onDelete(const std::vector<std::string>&)
{
// warn the user if the object has childs
// warn the user if the object has unselected children
auto objs = claimChildren();
if (!objs.empty())
{
// generate dialog
QString bodyMessage;
QTextStream bodyMessageStream(&bodyMessage);
bodyMessageStream << qApp->translate("Std_Delete",
"The functions list is not empty, therefore the\nfollowing referencing objects might be lost:");
bodyMessageStream << '\n';
for (auto ObjIterator : objs)
bodyMessageStream << '\n' << QString::fromUtf8(ObjIterator->Label.getValue());
bodyMessageStream << "\n\n" << QObject::tr("Are you sure you want to continue?");
// show and evaluate the dialog
int DialogResult = QMessageBox::warning(Gui::getMainWindow(),
qApp->translate("Std_Delete", "Object dependencies"), bodyMessage,
QMessageBox::Yes, QMessageBox::No);
if (DialogResult == QMessageBox::Yes)
return true;
else
return false;
}
else {
return true;
}
return ViewProviderFemAnalysis::checkSelectedChildren(
objs, this->getDocument(), "functions list");
}
bool ViewProviderFemPostFunctionProvider::canDelete(App::DocumentObject* obj) const
@@ -178,7 +157,6 @@ PROPERTY_SOURCE(FemGui::ViewProviderFemPostFunction, Gui::ViewProviderDocumentOb
ViewProviderFemPostFunction::ViewProviderFemPostFunction()
: m_manip(nullptr), m_autoscale(false), m_isDragging(false), m_autoRecompute(false)
{
ADD_PROPERTY_TYPE(AutoScaleFactorX, (1), "AutoScale", App::Prop_Hidden, "Automatic scaling factor");
ADD_PROPERTY_TYPE(AutoScaleFactorY, (1), "AutoScale", App::Prop_Hidden, "Automatic scaling factor");
ADD_PROPERTY_TYPE(AutoScaleFactorZ, (1), "AutoScale", App::Prop_Hidden, "Automatic scaling factor");
@@ -186,9 +164,6 @@ ViewProviderFemPostFunction::ViewProviderFemPostFunction()
m_geometrySeperator = new SoSeparator();
m_geometrySeperator->ref();
m_transform = new SoTransform();
m_transform->ref();
m_scale = new SoScale();
m_scale->ref();
m_scale->scaleFactor = SbVec3f(1, 1, 1);
@@ -199,7 +174,6 @@ ViewProviderFemPostFunction::~ViewProviderFemPostFunction()
m_geometrySeperator->unref();
m_manip->unref();
m_scale->unref();
//transform is unref'd when it is replaced by the dragger
}
void ViewProviderFemPostFunction::attach(App::DocumentObject* pcObj)
@@ -211,7 +185,7 @@ void ViewProviderFemPostFunction::attach(App::DocumentObject* pcObj)
color->diffuseColor.setValue(0, 0, 1);
color->transparency.setValue(0.5);
m_transform = new SoTransform;
SoTransform* transform = new SoTransform();
m_manip = setupManipulator();
m_manip->ref();
@@ -220,7 +194,7 @@ void ViewProviderFemPostFunction::attach(App::DocumentObject* pcObj)
pcEditNode->ref();
pcEditNode->addChild(color);
pcEditNode->addChild(m_transform);
pcEditNode->addChild(transform);
pcEditNode->addChild(m_geometrySeperator);
m_geometrySeperator->insertChild(m_scale, 0);
@@ -232,7 +206,7 @@ void ViewProviderFemPostFunction::attach(App::DocumentObject* pcObj)
SoSearchAction sa;
sa.setInterest(SoSearchAction::FIRST);
sa.setSearchingAll(FALSE);
sa.setNode(m_transform);
sa.setNode(transform);
sa.apply(pcEditNode);
SoPath* path = sa.getPath();
if (path) {

View File

@@ -140,7 +140,6 @@ protected:
SoTransformManip* getManipulator() {return m_manip;}
SoSeparator* getGeometryNode() {return m_geometrySeperator;}
SoScale* getScaleNode() {return m_scale;}
SoTransform* getTransformNode() {return m_transform;}
private:
static void dragStartCallback(void * data, SoDragger * d);
@@ -150,7 +149,6 @@ private:
SoSeparator* m_geometrySeperator;
SoTransformManip* m_manip;
SoScale* m_scale;
SoTransform* m_transform;
bool m_autoscale, m_isDragging, m_autoRecompute;
};

View File

@@ -62,6 +62,7 @@
#include "ViewProviderFemPostObject.h"
#include "TaskPostBoxes.h"
#include "ViewProviderAnalysis.h"
using namespace FemGui;
@@ -836,8 +837,8 @@ void ViewProviderFemPostObject::setupTaskDialog(TaskDlgPost* dlg)
dlg->appendBox(new TaskPostDisplay(this));
}
void ViewProviderFemPostObject::unsetEdit(int ModNum) {
void ViewProviderFemPostObject::unsetEdit(int ModNum)
{
if (ModNum == ViewProvider::Default) {
// and update the pad
//getSketchObject()->getDocument()->recompute();
@@ -903,33 +904,9 @@ void ViewProviderFemPostObject::OnChange(Base::Subject< int >& /*rCaller*/, int
bool ViewProviderFemPostObject::onDelete(const std::vector<std::string>&)
{
// warn the user if the object has childs
// warn the user if the object has unselected children
auto objs = claimChildren();
if (!objs.empty())
{
// generate dialog
QString bodyMessage;
QTextStream bodyMessageStream(&bodyMessage);
bodyMessageStream << qApp->translate("Std_Delete",
"The pipeline is not empty, therefore the\nfollowing "
"referencing objects might be lost:");
bodyMessageStream << '\n';
for (auto ObjIterator : objs)
bodyMessageStream << '\n' << QString::fromUtf8(ObjIterator->Label.getValue());
bodyMessageStream << "\n\n" << QObject::tr("Are you sure you want to continue?");
// show and evaluate the dialog
int DialogResult = QMessageBox::warning(Gui::getMainWindow(),
qApp->translate("Std_Delete", "Object dependencies"), bodyMessage,
QMessageBox::Yes, QMessageBox::No);
if (DialogResult == QMessageBox::Yes)
return true;
else
return false;
}
else {
return true;
}
return ViewProviderFemAnalysis::checkSelectedChildren(objs, this->getDocument(), "pipeline");
}
bool ViewProviderFemPostObject::canDelete(App::DocumentObject* obj) const

View File

@@ -133,7 +133,6 @@ void ViewProviderFemPostPipeline::onSelectionChanged(const Gui::SelectionChanges
void ViewProviderFemPostPipeline::updateColorBars()
{
// take all visible childs and update its shape coloring
auto children = claimChildren();
for (auto& child : children) {

View File

@@ -32,6 +32,7 @@
#include <Gui/MainWindow.h>
#include "ViewProviderSolver.h"
#include "ViewProviderAnalysis.h"
using namespace FemGui;
@@ -44,9 +45,7 @@ ViewProviderSolver::ViewProviderSolver()
}
ViewProviderSolver::~ViewProviderSolver()
{
}
{}
std::vector<std::string> ViewProviderSolver::getDisplayModes() const
{
@@ -55,32 +54,9 @@ std::vector<std::string> ViewProviderSolver::getDisplayModes() const
bool ViewProviderSolver::onDelete(const std::vector<std::string>&)
{
// warn the user if the object has childs
// warn the user if the object has unselected children
auto objs = claimChildren();
if (!objs.empty())
{
// generate dialog
QString bodyMessage;
QTextStream bodyMessageStream(&bodyMessage);
bodyMessageStream << qApp->translate("Std_Delete",
"The solver is not empty, therefore the\nfollowing referencing objects might be lost:");
bodyMessageStream << '\n';
for (auto ObjIterator : objs)
bodyMessageStream << '\n' << QString::fromUtf8(ObjIterator->Label.getValue());
bodyMessageStream << "\n\n" << QObject::tr("Are you sure you want to continue?");
// show and evaluate the dialog
int DialogResult = QMessageBox::warning(Gui::getMainWindow(),
qApp->translate("Std_Delete", "Object dependencies"), bodyMessage,
QMessageBox::Yes, QMessageBox::No);
if (DialogResult == QMessageBox::Yes)
return true;
else
return false;
}
else {
return true;
}
return ViewProviderFemAnalysis::checkSelectedChildren(objs, this->getDocument(), "solver");
}
bool ViewProviderSolver::canDelete(App::DocumentObject* obj) const

View File

@@ -742,8 +742,13 @@ def makePostVtkResult(
):
"""makePostVtkResult(document, base_result, [name]):
creates a FEM post processing result object (vtk based) to hold FEM results"""
obj = doc.addObject("Fem::FemPostPipeline", name)
Pipeline_Name = "Pipeline_" + name
obj = doc.addObject("Fem::FemPostPipeline", Pipeline_Name)
obj.load(base_result)
if FreeCAD.GuiUp:
obj.ViewObject.SelectionStyle = "BoundBox"
# to assure the user sees something, set the default to Surface
obj.ViewObject.DisplayMode = "Surface"
return obj

View File

@@ -81,11 +81,6 @@ def importFrd(
if len(m["Nodes"]) > 0:
mesh = importToolsFem.make_femmesh(m)
result_mesh_object = ObjectsFem.makeMeshResult(
doc,
"ResultMesh"
)
result_mesh_object.FemMesh = mesh
res_mesh_is_compacted = False
nodenumbers_for_compacted_mesh = []
@@ -107,9 +102,7 @@ def importFrd(
.format(result_name_prefix, eigenmode_number)
)
elif number_of_increments > 1:
if result_analysis_type == "buckling":
results_name = (
"{}BucklingFactor_{}_Results"
.format(result_name_prefix, step_time)
@@ -119,7 +112,6 @@ def importFrd(
"{}Time_{}_Results"
.format(result_name_prefix, step_time)
)
else:
results_name = (
"{}Results"
@@ -127,6 +119,9 @@ def importFrd(
)
res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
# create result mesh
result_mesh_object = ObjectsFem.makeMeshResult(doc, results_name + "_Mesh")
result_mesh_object.FemMesh = mesh
res_obj.Mesh = result_mesh_object
res_obj = importToolsFem.fill_femresult_mechanical(res_obj, result_set)
if analysis:
@@ -193,6 +188,31 @@ def importFrd(
# fill Stats
res_obj = resulttools.fill_femresult_stats(res_obj)
# create a results pipeline if not already existing
pipeline_name = "Pipeline_" + results_name
pipeline_obj = doc.getObject(pipeline_name)
if pipeline_obj is None:
pipeline_obj = ObjectsFem.makePostVtkResult(doc, res_obj, results_name)
pipeline_visibility = True
if analysis:
analysis.addObject(pipeline_obj)
else:
if FreeCAD.GuiUp:
# store pipeline visibility because pipeline_obj.load makes the
# pipeline always visible
pipeline_visibility = pipeline_obj.ViewObject.Visibility
pipeline_obj.load(res_obj)
# update the pipeline
pipeline_obj.recomputeChildren()
pipeline_obj.recompute()
if FreeCAD.GuiUp:
pipeline_obj.ViewObject.updateColorBars()
# make results mesh invisible, will be made visible
# later in task_solver_ccxtools.py
res_obj.Mesh.ViewObject.Visibility = False
# restore pipeline visibility
pipeline_obj.ViewObject.Visibility = pipeline_visibility
else:
error_message = (
"Nodes, but no results found in frd file. "

View File

@@ -65,11 +65,6 @@ class _TaskPanel:
# if Mesh and result are in active analysis
# activate the result mesh object
self.mesh_obj.ViewObject.show()
# hide pipeline if any
CCX_pipeline = FreeCADGui.ActiveDocument.getObject("SolverCCXResult")
if CCX_pipeline is not None:
self.pipeline_visibility = CCX_pipeline.Visibility
CCX_pipeline.hide()
ui_path = FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/"
self.result_widget = FreeCADGui.PySideUic.loadUi(ui_path + "ResultShow.ui")
@@ -195,12 +190,6 @@ class _TaskPanel:
self.result_widget.sb_displacement_factor_max.setValue(10. * scale_factor)
self.result_widget.sb_displacement_factor.setValue(scale_factor)
def __del__(self):
# restore visibility
CCX_pipeline = FreeCADGui.ActiveDocument.getObject("SolverCCXResult")
if self.pipeline_visibility and CCX_pipeline is not None:
CCX_pipeline.Visibility = self.pipeline_visibility
def restore_result_dialog(self):
try:
rt = FreeCAD.FEM_dialog["results_type"]

View File

@@ -78,7 +78,7 @@ class _TaskPanel:
self.CCX_mesh_visibility = False
# store visibility of possibly existing mesh object
CCX_mesh = self.fea.analysis.Document.getObject("ResultMesh")
CCX_mesh = self.fea.analysis.Document.getObject("CCX_Results_Mesh")
if CCX_mesh is not None:
self.CCX_mesh_visibility = CCX_mesh.ViewObject.Visibility
@@ -249,8 +249,6 @@ class _TaskPanel:
# print("calculixFinished(), exit code: {}".format(exitCode))
FreeCAD.Console.PrintLog("calculix state: {}\n".format(self.Calculix.state()))
had_errors = False
# Restore previous cwd
QtCore.QDir.setCurrent(self.cwd)
@@ -260,7 +258,6 @@ class _TaskPanel:
self.calculixNoError()
else:
self.calculixError()
had_errors = True
self.form.pb_run_ccx.setText("Re-run CalculiX")
self.femConsoleMessage("Loading result sets...")
@@ -290,47 +287,15 @@ class _TaskPanel:
self.fea.load_results()
except Exception:
FreeCAD.Console.PrintError("loading results failed\n")
had_errors = True
QApplication.restoreOverrideCursor()
self.form.l_time.setText("Time: {0:4.1f}: ".format(time.time() - self.Start))
# create a results pipeline from the just created results object
if not had_errors:
CCX_results = self.fea.analysis.Document.getObject("CCX_Results")
# safe guard
if CCX_results is None:
return
# check if there is already a pipeline
self.CCX_pipeline = self.fea.analysis.Document.getObject("SolverCCXResult")
if self.CCX_pipeline is None:
try:
self._createResults()
except Exception:
FreeCAD.Console.PrintError("Results pipeline could not be created\n")
had_errors = True
self.CCX_pipeline.load(CCX_results)
self.CCX_pipeline.recomputeChildren()
self.fea.analysis.Document.recompute()
# recompute() updated the result mesh data
# but not the shape and bar coloring
self.CCX_pipeline.ViewObject.updateColorBars()
# restore mesh object visibility
CCX_mesh = self.fea.analysis.Document.getObject("ResultMesh")
if CCX_mesh is not None:
CCX_mesh.ViewObject.Visibility = self.CCX_mesh_visibility
else:
FreeCAD.Console.PrintError("\nNo result pipeline was created.\n")
def _createResults(self):
self.CCX_pipeline = self.fea.analysis.Document.addObject(
"Fem::FemPostPipeline", "SolverCCXResult")
self.CCX_pipeline.Label = "SolverCCXResult"
self.CCX_pipeline.ViewObject.SelectionStyle = "BoundBox"
self.fea.analysis.addObject(self.CCX_pipeline)
# to assure the user sees something, set the default to Surface
self.CCX_pipeline.ViewObject.DisplayMode = "Surface"
# restore mesh object visibility
CCX_mesh = self.fea.analysis.Document.getObject("ResultMesh")
if CCX_mesh is not None:
CCX_mesh.ViewObject.Visibility = self.CCX_mesh_visibility
def choose_working_dir(self):
wd = QtGui.QFileDialog.getExistingDirectory(None, "Choose CalculiX working directory",
self.fea.working_dir)

View File

@@ -86,7 +86,7 @@ class TestObjectCreate(unittest.TestCase):
# thus they should not be counted
# solver children: equations --> 8
# gmsh mesh children: group, region, boundary layer --> 3
# resule children: mesh result --> 1
# result children: mesh result --> 1
# post pipeline children: region, scalar, cut, wrap --> 5
# analysis itself is not in analysis group --> 1
# thus: -18

Binary file not shown.

Binary file not shown.

View File

@@ -22,6 +22,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QLocale>
# include <QRegularExpression>
#endif
@@ -320,12 +321,26 @@ QString DimensionFormatter::formatValueToSpec(double value, QString formatSpecif
formattedValue.replace(QRegularExpression(QStringLiteral("([0-9][0-9]*\\.[0-9]*[1-9])00*$")), QStringLiteral("\\1"));
formattedValue.replace(QRegularExpression(QStringLiteral("([0-9][0-9]*)\\.0*$")), QStringLiteral("\\1"));
} else {
formattedValue = QString::asprintf(Base::Tools::toStdString(formatSpecifier).c_str(), value);
if (isNumericFormat(formatSpecifier)) {
formattedValue = QString::asprintf(Base::Tools::toStdString(formatSpecifier).c_str(), value);
}
}
return formattedValue;
}
bool DimensionFormatter::isNumericFormat(QString formatSpecifier)
{
QRegularExpression rxFormat(QStringLiteral("%[+-]?[0-9]*\\.*[0-9]*[aefgwAEFGW]")); //printf double format spec
QRegularExpressionMatch rxMatch;
int pos = formatSpecifier.indexOf(rxFormat, 0, &rxMatch);
if (pos != -1) {
return true;
}
return false;
}
//TODO: similiar code here and above
QStringList DimensionFormatter::getPrefixSuffixSpec(QString fSpec)
{
QStringList result;

View File

@@ -49,6 +49,7 @@ public:
std::string getDefaultFormatSpec(bool isToleranceFormat) const;
bool isTooSmall(double value, QString formatSpec);
QString formatValueToSpec(double value, QString formatSpecifier);
bool isNumericFormat(QString formatSpecifier);
private:
DrawViewDimension* m_dimension;

View File

@@ -282,7 +282,7 @@ TopoDS_Shape DrawComplexSection::prepareShape(const TopoDS_Shape& cutShape, doub
}
void DrawComplexSection::makeSectionCut(TopoDS_Shape& baseShape)
void DrawComplexSection::makeSectionCut(const TopoDS_Shape& baseShape)
{
// Base::Console().Message("DCS::makeSectionCut() - %s - baseShape.IsNull: %d\n",
// getNameInDocument(), baseShape.IsNull());
@@ -295,7 +295,11 @@ void DrawComplexSection::makeSectionCut(TopoDS_Shape& baseShape)
connectAlignWatcher =
QObject::connect(&m_alignWatcher, &QFutureWatcherBase::finished, &m_alignWatcher,
[this] { this->onSectionCutFinished(); });
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_alignFuture = QtConcurrent::run(this, &DrawComplexSection::makeAlignedPieces, baseShape);
#else
m_alignFuture = QtConcurrent::run(&DrawComplexSection::makeAlignedPieces, this, baseShape);
#endif
m_alignWatcher.setFuture(m_alignFuture);
waitingForAlign(true);
}

View File

@@ -58,7 +58,7 @@ public:
TopoDS_Compound alignSectionFaces(TopoDS_Shape faceIntersections) override;
std::pair<Base::Vector3d, Base::Vector3d> sectionLineEnds() override;
void makeSectionCut(TopoDS_Shape& baseShape) override;
void makeSectionCut(const TopoDS_Shape& baseShape) override;
void waitingForAlign(bool s) { m_waitingForAlign = s; }
bool waitingForAlign(void) const { return m_waitingForAlign; }

View File

@@ -186,7 +186,11 @@ void DrawViewDetail::detailExec(TopoDS_Shape& shape, DrawViewPart* dvp, DrawView
connectDetailWatcher =
QObject::connect(&m_detailWatcher, &QFutureWatcherBase::finished, &m_detailWatcher,
[this] { this->onMakeDetailFinished(); });
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_detailFuture = QtConcurrent::run(this, &DrawViewDetail::makeDetailShape, shape, dvp, dvs);
#else
m_detailFuture = QtConcurrent::run(&DrawViewDetail::makeDetailShape, this, shape, dvp, dvs);
#endif
m_detailWatcher.setFuture(m_detailFuture);
waitingForDetail(true);
}
@@ -194,7 +198,7 @@ void DrawViewDetail::detailExec(TopoDS_Shape& shape, DrawViewPart* dvp, DrawView
//this runs in a separate thread since it can sometimes take a long time
//make a common of the input shape and a cylinder (or prism depending on
//the matting style)
void DrawViewDetail::makeDetailShape(TopoDS_Shape& shape, DrawViewPart* dvp, DrawViewSection* dvs)
void DrawViewDetail::makeDetailShape(const TopoDS_Shape& shape, DrawViewPart* dvp, DrawViewSection* dvs)
{
showProgressMessage(getNameInDocument(), "is making detail shape");

View File

@@ -73,7 +73,7 @@ public:
void detailExec(TopoDS_Shape& s,
DrawViewPart* baseView,
DrawViewSection* sectionAlias);
void makeDetailShape(TopoDS_Shape& shape,
void makeDetailShape(const TopoDS_Shape& shape,
DrawViewPart* dvp,
DrawViewSection* dvs);
void postHlrTasks(void) override;

View File

@@ -390,7 +390,11 @@ TechDraw::GeometryObjectPtr DrawViewPart::buildGeometryObject(TopoDS_Shape& shap
//https://github.com/KDE/clazy/blob/1.11/docs/checks/README-connect-3arg-lambda.md
connectHlrWatcher = QObject::connect(&m_hlrWatcher, &QFutureWatcherBase::finished,
&m_hlrWatcher, [this] { this->onHlrFinished(); });
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_hlrFuture = QtConcurrent::run(go.get(), &GeometryObject::projectShape, shape, viewAxis);
#else
m_hlrFuture = QtConcurrent::run(&GeometryObject::projectShape, go.get(), shape, viewAxis);
#endif
m_hlrWatcher.setFuture(m_hlrFuture);
waitingForHlr(true);
}
@@ -430,7 +434,11 @@ void DrawViewPart::onHlrFinished(void)
connectFaceWatcher =
QObject::connect(&m_faceWatcher, &QFutureWatcherBase::finished, &m_faceWatcher,
[this] { this->onFacesFinished(); });
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_faceFuture = QtConcurrent::run(this, &DrawViewPart::extractFaces);
#else
m_faceFuture = QtConcurrent::run(&DrawViewPart::extractFaces, this);
#endif
m_faceWatcher.setFuture(m_faceFuture);
waitingForFaces(true);
}

View File

@@ -380,7 +380,11 @@ void DrawViewSection::sectionExec(TopoDS_Shape& baseShape)
connectCutWatcher =
QObject::connect(&m_cutWatcher, &QFutureWatcherBase::finished, &m_cutWatcher,
[this] { this->onSectionCutFinished(); });
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
m_cutFuture = QtConcurrent::run(this, &DrawViewSection::makeSectionCut, baseShape);
#else
m_cutFuture = QtConcurrent::run(&DrawViewSection::makeSectionCut, this, baseShape);
#endif
m_cutWatcher.setFuture(m_cutFuture);
waitingForCut(true);
}
@@ -390,7 +394,7 @@ void DrawViewSection::sectionExec(TopoDS_Shape& baseShape)
}
}
void DrawViewSection::makeSectionCut(TopoDS_Shape& baseShape)
void DrawViewSection::makeSectionCut(const TopoDS_Shape& baseShape)
{
// Base::Console().Message("DVS::makeSectionCut() - %s - baseShape.IsNull: %d\n",
// getNameInDocument(), baseShape.IsNull());

View File

@@ -116,7 +116,7 @@ public:
short mustExecute() const override;
void sectionExec(TopoDS_Shape& s);
virtual void makeSectionCut(TopoDS_Shape& baseShape);
virtual void makeSectionCut(const TopoDS_Shape& baseShape);
void postHlrTasks(void) override;
virtual void postSectionCutTasks();
void waitingForCut(bool s) { m_waitingForCut = s; }

View File

@@ -84,14 +84,13 @@ void loadTechDrawResource()
// add fonts
std::string fontDir = App::Application::getResourceDir() + "Mod/TechDraw/Resources/fonts/";
QFontDatabase fontDB;
std::vector<std::string> fontsAll(
{"osifont-lgpl3fe.ttf", "osifont-italic.ttf", "Y14.5-2018.ttf", "Y14.5-FreeCAD.ttf"});
for (auto& font : fontsAll) {
QString fontFile = Base::Tools::fromStdString(fontDir + font);
int rc = fontDB.addApplicationFont(fontFile);
int rc = QFontDatabase::addApplicationFont(fontFile);
if (rc < 0) {
Base::Console().Warning(
"TechDraw failed to load font file: %d from: %s\n", rc, qPrintable(fontFile));

View File

@@ -41,7 +41,8 @@
using namespace TechDrawGui;
QGIMatting::QGIMatting() :
m_radius(5.0)
m_radius(5.0),
m_fudge(1.01) // same as m_fudge in DrawViewDetail
{
setCacheMode(QGraphicsItem::NoCache);
@@ -58,25 +59,48 @@ QGIMatting::QGIMatting() :
m_border->setPen(m_pen);
m_border->setBrush(m_brush);
m_mat = new QGraphicsPathItem();
addToGroup(m_mat);
m_matPen.setColor(Qt::white);
m_matPen.setStyle(Qt::SolidLine);
m_matBrush.setStyle(Qt::SolidPattern);
m_matBrush.setColor(Qt::white);
m_mat->setPen(m_matPen);
m_mat->setBrush(m_matBrush);
setZValue(ZVALUE::MATTING);
}
void QGIMatting::draw()
{
prepareGeometryChange();
double penWidth = Rez::guiX(TechDraw::LineGroup::getDefaultWidth("Graphic"));
double penWidth_2 = penWidth / 2.0;
m_pen.setWidthF(penWidth);
double matSize = m_radius * m_fudge + 2 * penWidth; // outer bound of mat
m_matPen.setWidthF(2.0 * penWidth);
QPainterPath ppCut;
QPainterPath ppMat;
if (getHoleStyle() == 0) {
QRectF roundCutout (-m_radius, -m_radius, 2.0 * m_radius, 2.0 * m_radius);
ppCut.addEllipse(roundCutout);
QRectF roundMat(-matSize, -matSize, 2.0 * matSize, 2.0 * matSize);
ppMat.addEllipse(roundMat);
ppMat.addEllipse(roundCutout.adjusted(-penWidth_2, -penWidth_2, penWidth_2, penWidth_2));
} else {
double squareSize = m_radius;
QRectF squareCutout (-squareSize, -squareSize, 2.0 * squareSize, 2.0 * squareSize);
ppCut.addRect(squareCutout);
QRectF squareMat(-matSize, -matSize, 2.0 * matSize, 2.0 * matSize);
ppMat.addRect(squareMat);
ppMat.addRect(squareCutout.adjusted(-penWidth_2, -penWidth_2, penWidth_2, penWidth_2));
}
m_pen.setWidthF(Rez::guiX(TechDraw::LineGroup::getDefaultWidth("Graphic")));
m_border->setPen(m_pen);
m_border->setPath(ppCut);
m_border->setZValue(ZVALUE::MATTING);
m_mat->setPen(m_matPen);
m_mat->setPath(ppMat);
m_mat->setZValue(ZVALUE::MATTING - 1.0);
}
int QGIMatting::getHoleStyle()

View File

@@ -62,13 +62,17 @@ protected:
double m_height;
double m_width;
double m_radius;
double m_fudge;
int getHoleStyle();
QGraphicsPathItem* m_border;
QGraphicsPathItem* m_mat;
private:
QPen m_pen;
QBrush m_brush;
QPen m_matPen;
QBrush m_matBrush;
};

View File

@@ -545,21 +545,23 @@ QRectF QGIView::customChildrenBoundingRect() const
int editablePathItemType = QGraphicsItem::UserType + 301; // TODO: Magic number warning
int movableTextItemType = QGraphicsItem::UserType + 300;
int weldingSymbolItemType = QGraphicsItem::UserType + 340;
int centerMarkItemType = QGraphicsItem::UserType + 171;
QRectF result;
for (QList<QGraphicsItem*>::iterator it = children.begin(); it != children.end(); ++it) {
if (!(*it)->isVisible()) {
for (auto& child : children) {
if (!child->isVisible()) {
continue;
}
if ( ((*it)->type() != dimItemType) &&
((*it)->type() != leaderItemType) &&
((*it)->type() != textLeaderItemType) &&
((*it)->type() != editablePathItemType) &&
((*it)->type() != movableTextItemType) &&
((*it)->type() != borderItemType) &&
((*it)->type() != labelItemType) &&
((*it)->type() != weldingSymbolItemType) &&
((*it)->type() != captionItemType) ) {
QRectF childRect = mapFromItem(*it, (*it)->boundingRect()).boundingRect();
if ( (child->type() != dimItemType) &&
(child->type() != leaderItemType) &&
(child->type() != textLeaderItemType) &&
(child->type() != editablePathItemType) &&
(child->type() != movableTextItemType) &&
(child->type() != borderItemType) &&
(child->type() != labelItemType) &&
(child->type() != weldingSymbolItemType) &&
(child->type() != captionItemType) &&
(child->type() != centerMarkItemType)) {
QRectF childRect = mapFromItem(child, child->boundingRect()).boundingRect();
result = result.united(childRect);
//result = result.united((*it)->boundingRect());
}

View File

@@ -1259,7 +1259,9 @@ void QGSPage::postProcessXml(QTemporaryFile& temporaryFile, QString fileName, QS
QTextStream stream(&outFile);
stream.setGenerateByteOrderMark(false);
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
stream.setCodec("UTF-8");
#endif
stream << exportDoc.toByteArray();
outFile.close();

View File

@@ -27,7 +27,6 @@
#include <QApplication>
#include <QBitmap>
#include <QContextMenuEvent>
#include <QGLWidget>
#include <QLabel>
#include <QMouseEvent>
#include <QPaintEvent>
@@ -357,7 +356,6 @@ void QGVPage::setRenderer(RendererType type)
if (m_renderer == OpenGL) {
#ifndef QT_NO_OPENGL
// setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); //QGLWidget is obsolete
setViewport(new QOpenGLWidget);
setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
#endif
@@ -466,7 +464,11 @@ void QGVPage::kbPanScroll(int xMove, int yMove)
}
}
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void QGVPage::enterEvent(QEvent* event)
#else
void QGVPage::enterEvent(QEnterEvent* event)
#endif
{
QGraphicsView::enterEvent(event);
m_navStyle->handleEnterEvent(event);

View File

@@ -130,7 +130,11 @@ public Q_SLOTS:
protected:
void wheelEvent(QWheelEvent* event) override;
void paintEvent(QPaintEvent* event) override;
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
void enterEvent(QEvent* event) override;
#else
void enterEvent(QEnterEvent* event) override;
#endif
void leaveEvent(QEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;

View File

@@ -201,8 +201,7 @@ MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent)
// font size
QFontDatabase db;
const auto sizes = db.standardSizes();
const auto sizes = QFontDatabase::standardSizes();
for(int size: sizes) {
f_fontsize->addItem(QString::number(size));
}
@@ -430,7 +429,11 @@ void MRichTextEdit::textStyle(int index) {
}
if (index == ParagraphMonospace) {
fmt = cursor.charFormat();
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
fmt.setFontFamily(QString::fromUtf8("Monospace"));
#else
fmt.setFontFamilies(QStringList() << QString::fromUtf8("Monospace"));
#endif
fmt.setFontStyleHint(QFont::Monospace);
fmt.setFontFixedPitch(true);
}

View File

@@ -1,68 +1,76 @@
import FreeCAD
import unittest
from .TechDrawTestUtilities import createPageWithSVGTemplate
from PySide import QtCore
class DrawViewDimensionTest(unittest.TestCase):
def setUp(self):
"""Creates a page and 2 views"""
FreeCAD.newDocument("TDDim")
FreeCAD.setActiveDocument("TDDim")
FreeCAD.ActiveDocument = FreeCAD.getDocument("TDDim")
print("DVDTest.setUp()")
FreeCAD.newDocument("TDDimTest")
FreeCAD.setActiveDocument("TDDimTest")
FreeCAD.ActiveDocument = FreeCAD.getDocument("TDDimTest")
self.document = FreeCAD.ActiveDocument
# make source feature
FreeCAD.ActiveDocument.addObject("Part::Box", "Box")
FreeCAD.ActiveDocument.addObject("Part::Sphere", "Sphere")
self.document.addObject("Part::Box", "Box")
self.document.addObject("Part::Sphere", "Sphere")
# make a page
self.page = createPageWithSVGTemplate()
self.page = createPageWithSVGTemplate(self.document)
self.page.Scale = 5.0
# page.ViewObject.show() # unit tests run in console mode
# make Views
self.view1 = FreeCAD.ActiveDocument.addObject("TechDraw::DrawViewPart", "View")
FreeCAD.ActiveDocument.View.Source = [FreeCAD.ActiveDocument.Box]
self.view = self.document.addObject("TechDraw::DrawViewPart", "View")
self.page.addView(self.view)
self.view.Source = [self.document.Box]
self.view.X = 30
self.view.Y = 150
self.view1 = self.document.addObject("TechDraw::DrawViewPart", "View001")
self.page.addView(self.view1)
self.view1.X = 30
self.view1.Source = [self.document.Sphere]
self.view1.X = 220
self.view1.Y = 150
self.view2 = FreeCAD.activeDocument().addObject(
"TechDraw::DrawViewPart", "View001"
)
FreeCAD.activeDocument().View001.Source = [FreeCAD.activeDocument().Sphere]
self.page.addView(self.view2)
self.view2.X = 220
self.view2.Y = 150
FreeCAD.ActiveDocument.recompute()
self.document.recompute()
#wait for threads to complete before checking result
loop = QtCore.QEventLoop()
timer = QtCore.QTimer()
timer.setSingleShot(True)
timer.timeout.connect(loop.quit)
timer.start(5000) #5 second delay
loop.exec_()
def tearDown(self):
FreeCAD.closeDocument("TDDim")
print("DVDTest.tearDown()")
FreeCAD.closeDocument("TDDimTest")
def testLengthDimension(self):
"""Tests if a length dimension can be added to view1"""
"""Tests if a length dimension can be added to view"""
# make length dimension
print("making length dimension")
dimension = FreeCAD.ActiveDocument.addObject(
"TechDraw::DrawViewDimension", "Dimension"
)
dimension.Type = "Distance"
dimension.References2D = [(self.view1, "Edge1")]
print("adding dim1 to page")
dimension = self.document.addObject("TechDraw::DrawViewDimension", "Dimension")
self.page.addView(dimension)
dimension.Type = "Distance"
dimension.References2D = [(self.view, "Edge1")]
print("finished length dimension")
FreeCAD.ActiveDocument.recompute()
self.document.recompute()
self.assertTrue("Up-to-date" in dimension.State)
def testRadiusDimension(self):
"""Tests if a radius dimension can be added to view2"""
"""Tests if a radius dimension can be added to view1"""
print("making radius dimension")
dimension = FreeCAD.ActiveDocument.addObject(
"TechDraw::DrawViewDimension", "Dimension001"
)
dimension = self.document.addObject("TechDraw::DrawViewDimension", "Dimension001")
self.page.addView(dimension)
dimension.Type = "Radius"
dimension.MeasureType = "Projected"
dimension.References2D = [(self.view2, "Edge0")]
self.page.addView(dimension)
FreeCAD.ActiveDocument.recompute()
dimension.References2D = [(self.view1, "Edge0")]
self.document.recompute()
self.assertTrue("Up-to-date" in dimension.State)

View File

@@ -2,13 +2,16 @@ import FreeCAD
import os
def createPageWithSVGTemplate():
def createPageWithSVGTemplate(doc=None):
"""Returns a page with an SVGTemplate added on the ActiveDocument"""
path = os.path.dirname(os.path.abspath(__file__))
templateFileSpec = path + "/TestTemplate.svg"
if not doc:
doc = FreeCAD.ActiveDocument
page = FreeCAD.ActiveDocument.addObject("TechDraw::DrawPage", "Page")
FreeCAD.ActiveDocument.addObject("TechDraw::DrawSVGTemplate", "Template")
FreeCAD.ActiveDocument.Template.Template = templateFileSpec
FreeCAD.ActiveDocument.Page.Template = FreeCAD.ActiveDocument.Template
page = doc.addObject("TechDraw::DrawPage", "Page")
doc.addObject("TechDraw::DrawSVGTemplate", "Template")
doc.Template.Template = templateFileSpec
doc.Page.Template = doc.Template
return page

View File

@@ -24,7 +24,6 @@
from TDTest.DrawHatchTest import DrawHatchTest # noqa: F401
from TDTest.DrawViewAnnotationTest import DrawViewAnnotationTest # noqa: F401
from TDTest.DrawViewBalloonTest import DrawViewBalloonTest # noqa: F401
from TDTest.DrawViewDimensionTest import DrawViewDimensionTest # noqa: F401
from TDTest.DrawViewImageTest import DrawViewImageTest # noqa: F401
from TDTest.DrawViewSymbolTest import DrawViewSymbolTest # noqa: F401
from TDTest.DrawProjectionGroupTest import DrawProjectionGroupTest # noqa: F401

View File

@@ -25,3 +25,5 @@
from TDTest.DrawViewSectionTest import DrawViewSectionTest # noqa: F401
from TDTest.DrawViewPartTest import DrawViewPartTest # noqa: F401
from TDTest.DrawViewDetailTest import DrawViewDetailTest # noqa: F401
from TDTest.DrawViewDimensionTest import DrawViewDimensionTest # noqa: F401