Merge branch 'master' into path_custom_source
This commit is contained in:
62
.github/workflows/actions/runCPPTests/action.yml
vendored
Normal file
62
.github/workflows/actions/runCPPTests/action.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2023 0penBrain *
|
||||
# * Copyright (c) 2023 FreeCAD Project Association *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
name: runCPPTests
|
||||
description: "Run: C++ tests"
|
||||
|
||||
inputs:
|
||||
testCommand:
|
||||
description: "Test command to be run"
|
||||
required: true
|
||||
testLogFile:
|
||||
description: "Path for the command-line output of the tests"
|
||||
required: true
|
||||
reportFile:
|
||||
description: "Report file"
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Run GTest unit tests
|
||||
id: runGoogleTests
|
||||
shell: bash
|
||||
run: stdbuf -oL -eL ${{ inputs.testCommand }} |& tee -a ${{ inputs.testLogFile }}
|
||||
- name: Parse test results
|
||||
if: always()
|
||||
shell: bash
|
||||
run: |
|
||||
result=$(sed -ne "/Global test environment tear-down/,/^$/{/^$/d;p}" ${{ inputs.testLogFile }})
|
||||
if [ $(echo $result | grep -F "[ FAILED ]") ]
|
||||
then
|
||||
echo "<details><summary>:fire: GTest C++ unit test suite failed</summary>" >> ${{ inputs.reportFile }}
|
||||
else
|
||||
echo "<details><summary>:heavy_check_mark: GTest C++ unit test suite succeeded</summary>" >> ${{ inputs.reportFile }}
|
||||
fi
|
||||
echo "" >> ${{ inputs.reportFile }}
|
||||
echo "Results" >> ${{ inputs.reportFile }}
|
||||
echo "" >> ${{ inputs.reportFile }}
|
||||
echo '```' >> ${{ inputs.reportFile }}
|
||||
echo "$result" >> ${{ inputs.reportFile }}
|
||||
echo '```' >> ${{ inputs.reportFile }}
|
||||
echo "</details>">> ${{ inputs.reportFile }}
|
||||
echo "" >> ${{ inputs.reportFile }}
|
||||
@@ -1,5 +1,5 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2023 0penBrain *
|
||||
# * Copyright (c) 2023 0penBrain *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
@@ -19,15 +19,15 @@
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
|
||||
name: runTests
|
||||
description: "Linux: run unit tests, generate log and report"
|
||||
name: runPythonTests
|
||||
description: "Linux: run Python tests, generate log and report"
|
||||
|
||||
inputs:
|
||||
testDescription:
|
||||
description: "Test description text, will be used on report"
|
||||
required: true
|
||||
testCommand:
|
||||
description: "Test command to be ran"
|
||||
description: "Test command to be run"
|
||||
required: true
|
||||
logFile:
|
||||
description: "Path for log file"
|
||||
15
.github/workflows/sub_buildUbuntu2004.yml
vendored
15
.github/workflows/sub_buildUbuntu2004.yml
vendored
@@ -185,7 +185,7 @@ jobs:
|
||||
- name: FreeCAD CLI tests on build dir
|
||||
if: inputs.testOnBuildDir
|
||||
timeout-minutes: 10
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "CLI tests on build dir"
|
||||
testCommand: ${{ env.builddir }}bin/FreeCADCmd -t 0
|
||||
@@ -194,12 +194,19 @@ jobs:
|
||||
- name: FreeCAD GUI tests on build dir
|
||||
if: inputs.testOnBuildDir
|
||||
timeout-minutes: 15
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "GUI tests on build dir"
|
||||
testCommand: xvfb-run ${{ env.builddir }}/bin/FreeCAD -t 0
|
||||
logFile: ${{ env.logdir }}TestGUIBuild.log
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: C++ unit tests
|
||||
timeout-minutes: 1
|
||||
uses: ./.github/workflows/actions/runCPPTests
|
||||
with:
|
||||
testCommand: ${{ env.builddir }}/tests/Tests_run --gtest_output=json:${{env.reportdir}}gtest_results.json
|
||||
testLogFile: ${{env.reportdir}}gtest_test_log.txt
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: CMake Install
|
||||
uses: ./.github/workflows/actions/linux/install
|
||||
with:
|
||||
@@ -209,7 +216,7 @@ jobs:
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: FreeCAD CLI tests on install
|
||||
timeout-minutes: 10
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "CLI tests on install"
|
||||
testCommand: FreeCADCmd -t 0
|
||||
@@ -217,7 +224,7 @@ jobs:
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: FreeCAD GUI tests on install
|
||||
timeout-minutes: 15
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "GUI tests on install"
|
||||
testCommand: xvfb-run FreeCAD -t 0
|
||||
|
||||
17
.github/workflows/sub_buildUbuntu2204.yml
vendored
17
.github/workflows/sub_buildUbuntu2204.yml
vendored
@@ -1,5 +1,5 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2023 0penBrain *
|
||||
# * Copyright (c) 2023 0penBrain *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify *
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
@@ -194,7 +194,7 @@ jobs:
|
||||
- name: FreeCAD CLI tests on build dir
|
||||
if: inputs.testOnBuildDir
|
||||
timeout-minutes: 10
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "CLI tests on build dir"
|
||||
testCommand: ${{ env.builddir }}bin/FreeCADCmd -t 0
|
||||
@@ -203,12 +203,19 @@ jobs:
|
||||
- name: FreeCAD GUI tests on build dir
|
||||
if: inputs.testOnBuildDir
|
||||
timeout-minutes: 15
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "GUI tests on build dir"
|
||||
testCommand: xvfb-run ${{ env.builddir }}/bin/FreeCAD -t 0
|
||||
logFile: ${{ env.logdir }}TestGUIBuild.log
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: C++ unit tests
|
||||
timeout-minutes: 1
|
||||
uses: ./.github/workflows/actions/runCPPTests
|
||||
with:
|
||||
testCommand: ${{ env.builddir }}/tests/Tests_run --gtest_output=json:${{env.reportdir}}gtest_results.json
|
||||
testLogFile: ${{env.reportdir}}gtest_test_log.txt
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: CMake Install
|
||||
uses: ./.github/workflows/actions/linux/install
|
||||
with:
|
||||
@@ -218,7 +225,7 @@ jobs:
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: FreeCAD CLI tests on install
|
||||
timeout-minutes: 10
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "CLI tests on install"
|
||||
testCommand: FreeCADCmd -t 0
|
||||
@@ -226,7 +233,7 @@ jobs:
|
||||
reportFile: ${{env.reportdir}}${{ env.reportfilename }}
|
||||
- name: FreeCAD GUI tests on install
|
||||
timeout-minutes: 15
|
||||
uses: ./.github/workflows/actions/runTests
|
||||
uses: ./.github/workflows/actions/runPythonTests
|
||||
with:
|
||||
testDescription: "GUI tests on install"
|
||||
testCommand: xvfb-run FreeCAD -t 0
|
||||
|
||||
2
.github/workflows/sub_lint.yml
vendored
2
.github/workflows/sub_lint.yml
vendored
@@ -39,7 +39,7 @@ on:
|
||||
type: string
|
||||
required: true
|
||||
checkLineendings:
|
||||
default: true
|
||||
default: false
|
||||
type: boolean
|
||||
required: false
|
||||
lineendingsFailSilent:
|
||||
|
||||
@@ -154,6 +154,8 @@ std::string Base::Tools::addNumber(const std::string& name, unsigned int num, in
|
||||
|
||||
std::string Base::Tools::getIdentifier(const std::string& name)
|
||||
{
|
||||
if (name.empty())
|
||||
return "_";
|
||||
// check for first character whether it's a digit
|
||||
std::string CleanName = name;
|
||||
if (!CleanName.empty() && CleanName[0] >= 48 && CleanName[0] <= 57)
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
# include <QWindow>
|
||||
#endif
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <Base/Console.h>
|
||||
@@ -1670,6 +1672,18 @@ Gui::PreferencePackManager* Application::prefPackManager()
|
||||
//**************************************************************************
|
||||
// Init, Destruct and singleton
|
||||
|
||||
namespace {
|
||||
void setCategoryFilterRules()
|
||||
{
|
||||
QString filter;
|
||||
QTextStream stream(&filter);
|
||||
stream << "qt.qpa.xcb.warning=false\n";
|
||||
stream << "qt.qpa.mime.warning=false\n";
|
||||
stream.flush();
|
||||
QLoggingCategory::setFilterRules(filter);
|
||||
}
|
||||
}
|
||||
|
||||
using _qt_msg_handler_old = void (*)(QtMsgType, const QMessageLogContext &, const QString &);
|
||||
_qt_msg_handler_old old_qtmsg_handler = nullptr;
|
||||
|
||||
@@ -1755,6 +1769,7 @@ void Application::initApplication()
|
||||
initTypes();
|
||||
new Base::ScriptProducer( "FreeCADGuiInit", FreeCADGuiInit );
|
||||
init_resources();
|
||||
setCategoryFilterRules();
|
||||
old_qtmsg_handler = qInstallMessageHandler(messageHandler);
|
||||
init = true;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
515
src/Mod/Draft/Resources/icons/Draft_LayerManager.svg
Normal file
515
src/Mod/Draft/Resources/icons/Draft_LayerManager.svg
Normal 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 |
94
src/Mod/Draft/Resources/ui/dialogLayers.ui
Normal file
94
src/Mod/Draft/Resources/ui/dialogLayers.ui
Normal 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>
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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())
|
||||
|
||||
## @}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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. "
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
/*------------------------------------------------------
|
||||
CCmdLine
|
||||
|
||||
A utility for parsing command lines.
|
||||
|
||||
Copyright (C) 1999 Chris Losinger, Smaller Animals Software.
|
||||
http://www.smalleranimals.com
|
||||
|
||||
This software is provided 'as-is', without any express
|
||||
or implied warranty. In no event will the authors be
|
||||
held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software
|
||||
for any purpose, including commercial applications, and
|
||||
to alter it and redistribute it freely, subject to the
|
||||
following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
See SACmds.h for more info.
|
||||
------------------------------------------------------*/
|
||||
|
||||
// if you're using MFC, you'll need to un-comment this line
|
||||
// #include "stdafx.h"
|
||||
|
||||
#include "CmdLine.h"
|
||||
#ifdef Q_WS_WIN
|
||||
# include "crtdbg.h"
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------
|
||||
int CCmdLine::SplitLine(int argc, char **argv)
|
||||
|
||||
parse the command line into switches and arguments
|
||||
|
||||
returns number of switches found
|
||||
------------------------------------------------------*/
|
||||
int CCmdLine::SplitLine(int argc, char **argv)
|
||||
{
|
||||
clear();
|
||||
|
||||
StringType curParam; // current argv[x]
|
||||
|
||||
// skip the exe name (start with i = 1)
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
// if it's a switch, start a new CCmdLine
|
||||
if (IsSwitch(argv[i]))
|
||||
{
|
||||
curParam = argv[i];
|
||||
|
||||
StringType arg;
|
||||
|
||||
// look at next input string to see if it's a switch or an argument
|
||||
if (i + 1 < argc)
|
||||
{
|
||||
if (!IsSwitch(argv[i + 1]))
|
||||
{
|
||||
// it's an argument, not a switch
|
||||
arg = argv[i + 1];
|
||||
|
||||
// skip to next
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = "";
|
||||
}
|
||||
}
|
||||
|
||||
// add it
|
||||
CCmdParam cmd;
|
||||
|
||||
// only add non-empty args
|
||||
if (arg != "")
|
||||
{
|
||||
cmd.m_strings.push_back(arg);
|
||||
}
|
||||
|
||||
// add the CCmdParam to 'this'
|
||||
pair<CCmdLine::iterator, bool> res = insert(CCmdLine::value_type(curParam, cmd));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's not a new switch, so it must be more stuff for the last switch
|
||||
|
||||
// ...let's add it
|
||||
CCmdLine::iterator theIterator;
|
||||
|
||||
// get an iterator for the current param
|
||||
theIterator = find(curParam);
|
||||
if (theIterator!=end())
|
||||
{
|
||||
(*theIterator).second.m_strings.push_back(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ??
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------
|
||||
|
||||
protected member function
|
||||
test a parameter to see if it's a switch :
|
||||
|
||||
switches are of the form : -x
|
||||
where 'x' is one or more characters.
|
||||
the first character of a switch must be non-numeric!
|
||||
|
||||
------------------------------------------------------*/
|
||||
|
||||
bool CCmdLine::IsSwitch(const char *pParam)
|
||||
{
|
||||
if (pParam==NULL)
|
||||
return false;
|
||||
|
||||
// switches must non-empty
|
||||
// must have at least one character after the '-'
|
||||
int len = strlen(pParam);
|
||||
if (len <= 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// switches always start with '-'
|
||||
if (pParam[0]=='-')
|
||||
{
|
||||
// allow negative numbers as arguments.
|
||||
// ie., don't count them as switches
|
||||
#ifdef Q_WS_WIN
|
||||
return (!isdigit(pParam[1]));
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------
|
||||
bool CCmdLine::HasSwitch(const char *pSwitch)
|
||||
|
||||
was the switch found on the command line ?
|
||||
|
||||
ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
|
||||
|
||||
call return
|
||||
---- ------
|
||||
cmdLine.HasSwitch("-a") true
|
||||
cmdLine.HasSwitch("-z") false
|
||||
------------------------------------------------------*/
|
||||
|
||||
bool CCmdLine::HasSwitch(const char *pSwitch)
|
||||
{
|
||||
CCmdLine::iterator theIterator;
|
||||
theIterator = find(pSwitch);
|
||||
return (theIterator!=end());
|
||||
}
|
||||
|
||||
/*------------------------------------------------------
|
||||
|
||||
StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault)
|
||||
|
||||
fetch an argument associated with a switch . if the parameter at
|
||||
index iIdx is not found, this will return the default that you
|
||||
provide.
|
||||
|
||||
example :
|
||||
|
||||
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
|
||||
|
||||
call return
|
||||
---- ------
|
||||
cmdLine.GetSafeArgument("-a", 0, "zz") p1
|
||||
cmdLine.GetSafeArgument("-a", 1, "zz") p2
|
||||
cmdLine.GetSafeArgument("-b", 0, "zz") p4
|
||||
cmdLine.GetSafeArgument("-b", 1, "zz") zz
|
||||
|
||||
------------------------------------------------------*/
|
||||
|
||||
StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault)
|
||||
{
|
||||
StringType sRet;
|
||||
|
||||
if (pDefault!=NULL)
|
||||
sRet = pDefault;
|
||||
|
||||
try
|
||||
{
|
||||
sRet = GetArgument(pSwitch, iIdx);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
return sRet;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------
|
||||
|
||||
StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx)
|
||||
|
||||
fetch a argument associated with a switch. throws an exception
|
||||
of (int)0, if the parameter at index iIdx is not found.
|
||||
|
||||
example :
|
||||
|
||||
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
|
||||
|
||||
call return
|
||||
---- ------
|
||||
cmdLine.GetArgument("-a", 0) p1
|
||||
cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string
|
||||
|
||||
------------------------------------------------------*/
|
||||
|
||||
StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx)
|
||||
{
|
||||
if (HasSwitch(pSwitch))
|
||||
{
|
||||
CCmdLine::iterator theIterator;
|
||||
|
||||
theIterator = find(pSwitch);
|
||||
if (theIterator!=end())
|
||||
{
|
||||
if ((*theIterator).second.m_strings.size() > (unsigned)iIdx)
|
||||
{
|
||||
return (*theIterator).second.m_strings[iIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw (int)0;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*------------------------------------------------------
|
||||
int CCmdLine::GetArgumentCount(const char *pSwitch)
|
||||
|
||||
returns the number of arguments found for a given switch.
|
||||
|
||||
returns -1 if the switch was not found
|
||||
|
||||
------------------------------------------------------*/
|
||||
|
||||
int CCmdLine::GetArgumentCount(const char *pSwitch)
|
||||
{
|
||||
int iArgumentCount = -1;
|
||||
|
||||
if (HasSwitch(pSwitch))
|
||||
{
|
||||
CCmdLine::iterator theIterator;
|
||||
|
||||
theIterator = find(pSwitch);
|
||||
if (theIterator!=end())
|
||||
{
|
||||
iArgumentCount = (*theIterator).second.m_strings.size();
|
||||
}
|
||||
}
|
||||
|
||||
return iArgumentCount;
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
/*------------------------------------------------------
|
||||
CCmdLine
|
||||
|
||||
A utility for parsing command lines.
|
||||
|
||||
Copyright (C) 1999 Chris Losinger, Smaller Animals Software.
|
||||
http://www.smalleranimals.com
|
||||
|
||||
This software is provided 'as-is', without any express
|
||||
or implied warranty. In no event will the authors be
|
||||
held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software
|
||||
for any purpose, including commercial applications, and
|
||||
to alter it and redistribute it freely, subject to the
|
||||
following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented;
|
||||
you must not claim that you wrote the original software.
|
||||
If you use this software in a product, an acknowledgment
|
||||
in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such,
|
||||
and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
-------------------------
|
||||
|
||||
Example :
|
||||
|
||||
Our example application uses a command line that has two
|
||||
required switches and two optional switches. The app should abort
|
||||
if the required switches are not present and continue with default
|
||||
values if the optional switches are not present.
|
||||
|
||||
Sample command line :
|
||||
MyApp.exe -p1 text1 text2 -p2 "this is a big argument" -opt1 -55 -opt2
|
||||
|
||||
Switches -p1 and -p2 are required.
|
||||
p1 has two arguments and p2 has one.
|
||||
|
||||
Switches -opt1 and -opt2 are optional.
|
||||
opt1 requires a numeric argument.
|
||||
opt2 has no arguments.
|
||||
|
||||
Also, assume that the app displays a 'help' screen if the '-h' switch
|
||||
is present on the command line.
|
||||
|
||||
#include "CmdLine.h"
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
// our cmd line parser object
|
||||
CCmdLine cmdLine;
|
||||
|
||||
// parse argc,argv
|
||||
if (cmdLine.SplitLine(argc, argv) < 1)
|
||||
{
|
||||
// no switches were given on the command line, abort
|
||||
ASSERT(0);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// test for the 'help' case
|
||||
if (cmdLine.HasSwitch("-h"))
|
||||
{
|
||||
show_help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// get the required arguments
|
||||
StringType p1_1, p1_2, p2_1;
|
||||
try
|
||||
{
|
||||
// if any of these fail, we'll end up in the catch() block
|
||||
p1_1 = cmdLine.GetArgument("-p1", 0);
|
||||
p1_2 = cmdLine.GetArgument("-p1", 1);
|
||||
p2_1 = cmdLine.GetArgument("-p2", 0);
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// one of the required arguments was missing, abort
|
||||
ASSERT(0);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// get the optional parameters
|
||||
|
||||
// convert to an int, default to '100'
|
||||
int iOpt1Val = atoi(cmdLine.GetSafeArgument("-opt1", 0, 100));
|
||||
|
||||
// since opt2 has no arguments, just test for the presence of
|
||||
// the '-opt2' switch
|
||||
bool bOptVal2 = cmdLine.HasSwitch("-opt2");
|
||||
|
||||
.... and so on....
|
||||
|
||||
}
|
||||
|
||||
If this class is used in an MFC application, StringType is CString, else
|
||||
it uses the STL 'string' type.
|
||||
|
||||
If this is an MFC app, you can use the __argc and __argv macros from
|
||||
you CYourWinApp::InitInstance() function in place of the standard argc
|
||||
and argv variables.
|
||||
|
||||
------------------------------------------------------*/
|
||||
#ifndef SACMDSH
|
||||
#define SACMDSH
|
||||
|
||||
|
||||
#ifdef __AFX_H__
|
||||
// if we're using MFC, use CStrings
|
||||
#define StringType CString
|
||||
#else
|
||||
// if we're not using MFC, use STL strings
|
||||
#define StringType string
|
||||
#endif
|
||||
|
||||
// tell the compiler to shut up
|
||||
#pragma warning(disable:4786)
|
||||
|
||||
//#include <iostream> // you may need this
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace std ;
|
||||
|
||||
// handy little container for our argument vector
|
||||
struct CCmdParam
|
||||
{
|
||||
vector<StringType> m_strings;
|
||||
};
|
||||
|
||||
// this class is actually a map of strings to vectors
|
||||
using _CCmdLine = map<StringType, CCmdParam>;
|
||||
|
||||
// the command line parser class
|
||||
class CCmdLine : public _CCmdLine
|
||||
{
|
||||
|
||||
public:
|
||||
/*------------------------------------------------------
|
||||
int CCmdLine::SplitLine(int argc, char **argv)
|
||||
|
||||
parse the command line into switches and arguments.
|
||||
|
||||
returns number of switches found
|
||||
------------------------------------------------------*/
|
||||
int SplitLine(int argc, char **argv);
|
||||
|
||||
/*------------------------------------------------------
|
||||
bool CCmdLine::HasSwitch(const char *pSwitch)
|
||||
|
||||
was the switch found on the command line ?
|
||||
|
||||
ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
|
||||
|
||||
call return
|
||||
---- ------
|
||||
cmdLine.HasSwitch("-a") true
|
||||
cmdLine.HasSwitch("-z") false
|
||||
------------------------------------------------------*/
|
||||
bool HasSwitch(const char *pSwitch);
|
||||
|
||||
/*------------------------------------------------------
|
||||
|
||||
StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault)
|
||||
|
||||
fetch an argument associated with a switch . if the parameter at
|
||||
index iIdx is not found, this will return the default that you
|
||||
provide.
|
||||
|
||||
example :
|
||||
|
||||
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
|
||||
|
||||
call return
|
||||
---- ------
|
||||
cmdLine.GetSafeArgument("-a", 0, "zz") p1
|
||||
cmdLine.GetSafeArgument("-a", 1, "zz") p2
|
||||
cmdLine.GetSafeArgument("-b", 0, "zz") p4
|
||||
cmdLine.GetSafeArgument("-b", 1, "zz") zz
|
||||
|
||||
------------------------------------------------------*/
|
||||
|
||||
StringType GetSafeArgument(const char *pSwitch, int iIdx, const char *pDefault);
|
||||
|
||||
/*------------------------------------------------------
|
||||
|
||||
StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx)
|
||||
|
||||
fetch a argument associated with a switch. throws an exception
|
||||
of (int)0, if the parameter at index iIdx is not found.
|
||||
|
||||
example :
|
||||
|
||||
command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5
|
||||
|
||||
call return
|
||||
---- ------
|
||||
cmdLine.GetArgument("-a", 0) p1
|
||||
cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string
|
||||
|
||||
------------------------------------------------------*/
|
||||
StringType GetArgument(const char *pSwitch, int iIdx);
|
||||
|
||||
/*------------------------------------------------------
|
||||
int CCmdLine::GetArgumentCount(const char *pSwitch)
|
||||
|
||||
returns the number of arguments found for a given switch.
|
||||
|
||||
returns -1 if the switch was not found
|
||||
|
||||
------------------------------------------------------*/
|
||||
int GetArgumentCount(const char *pSwitch);
|
||||
|
||||
protected:
|
||||
/*------------------------------------------------------
|
||||
|
||||
protected member function
|
||||
test a parameter to see if it's a switch :
|
||||
|
||||
switches are of the form : -x
|
||||
where 'x' is one or more characters.
|
||||
the first character of a switch must be non-numeric!
|
||||
|
||||
------------------------------------------------------*/
|
||||
bool IsSwitch(const char *pParam);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,9 +0,0 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += debug console
|
||||
TARGET +=
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
|
||||
# Input
|
||||
HEADERS += CmdLine.h imageconv.h
|
||||
SOURCES += CmdLine.cpp imageconv.cpp main.cpp
|
||||
@@ -1,146 +0,0 @@
|
||||
<!--#include virtual="header.shtml" -->
|
||||
|
||||
<CENTER><H3><FONT COLOR="#AOAO99">
|
||||
CCmdLine - a class for parsing command line with or without MFC
|
||||
</FONT></H3></CENTER><HR>
|
||||
|
||||
<!-- Author and contact details -->
|
||||
This article was contributed by <A HREF="mailto:smallest@smalleranimals.com">Chris Losinger</A>.
|
||||
|
||||
<!-- Environment eg NT 4.0 SP3, VC6.0 SP1 -->
|
||||
<p>Environment: All</u>
|
||||
|
||||
<!-- Text / source code -->
|
||||
<p>
|
||||
<!-- The 'p' starts a paragraph of normal text -->
|
||||
|
||||
CCmdLine is a simple way to parse a command line into <i>switches</i> and <i>arguments</i>.
|
||||
Ex :
|
||||
<br>
|
||||
<ul>
|
||||
MyApp.exe -sw1 arg1 arg2 -sw2 arg3 -sw3 -sw4
|
||||
</ul>
|
||||
<br>
|
||||
When using CCmdLine, "-sw1", "-sw2", "-sw3" and "-sw4" are <i>switches</i> and "arg1", "arg2" and "arg3" are <i>arguments</i>.
|
||||
<p>
|
||||
Parsing command lines with the standard C string functions (strlen, strcpy, etc.) or even
|
||||
with the CString operators is a nightmare. But, CCmdLine makes it effortless.
|
||||
<p>
|
||||
CCmdLine was written for use with console apps, but can be easily used in
|
||||
any application which requires command-line parsing.
|
||||
<p>
|
||||
CCmdLine uses STL for its collection classes, so it works in MFC
|
||||
and non-MFC apps. If you are using this in an MFC app, the switches
|
||||
and arguments will be returned as CStrings. If you are using this in a
|
||||
non-MFC app, they will be returned as STL 'string's.
|
||||
<p>
|
||||
<hr>
|
||||
Example :
|
||||
|
||||
Assume the application we're writing uses a command line that has two
|
||||
required switches and two optional switches. The app should abort
|
||||
if the required switches are not present and continue with default
|
||||
values if the optional switches are not present.
|
||||
<ul>
|
||||
Sample command line :
|
||||
<br>
|
||||
<pre>
|
||||
MyApp.exe -p1 text1 text2 -p2 "this is a big argument" -opt1 -55 -opt2
|
||||
</pre>
|
||||
Switches -p1 and -p2 are required.
|
||||
<br>
|
||||
p1 has two arguments and p2 has one.
|
||||
<br>
|
||||
<br>
|
||||
Switches -opt1 and -opt2 are optional.
|
||||
<br>
|
||||
opt1 requires a numeric argument.
|
||||
<br>
|
||||
opt2 has no arguments.
|
||||
<br>
|
||||
<br>
|
||||
Also, assume that the app displays a 'help' screen if the '-h' switch
|
||||
is present on the command line.
|
||||
</ul>
|
||||
Here's how you can use CCmdLine to handle this :
|
||||
<hr>
|
||||
<!-- start a block of source code -->
|
||||
<PRE><TT><FONT COLOR="#990000">
|
||||
// if this is an MFC app, uncomment this line
|
||||
// #include "stdafx.h"
|
||||
|
||||
#include "CmdLine.h"
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
// our cmd line parser object
|
||||
CCmdLine cmdLine;
|
||||
|
||||
// parse the command line
|
||||
// use __argc and __argv, in MFC apps
|
||||
if (cmdLine.SplitLine(argc, argv) < 1)
|
||||
{
|
||||
// no switches were given on the command line, abort
|
||||
ASSERT(0);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// test for the 'help' case
|
||||
if (cmdLine.HasSwitch("-h"))
|
||||
{
|
||||
show_help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// StringType is CString when using MFC, else STL's 'string'
|
||||
StringType p1_1, p1_2, p2_1;
|
||||
|
||||
// get the required arguments
|
||||
try
|
||||
{
|
||||
// if any of these GetArgument calls fail,
|
||||
// we'll end up in the catch() block
|
||||
|
||||
// get the first -p1 argument
|
||||
p1_1 = cmdLine.GetArgument("-p1", 0);
|
||||
|
||||
// get the second -p1 argument
|
||||
p1_2 = cmdLine.GetArgument("-p1", 1);
|
||||
|
||||
// get the first -p2 argument
|
||||
p2_1 = cmdLine.GetArgument("-p2", 0);
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// one of the required arguments was missing, abort
|
||||
ASSERT(0);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// get the optional parameters
|
||||
|
||||
// GetSafeArgument does not throw exceptions, and allows for
|
||||
// the use of a default value, in case the switch is not found
|
||||
// convert to an int, default to '100'
|
||||
int iOpt1Val = atoi( cmdLine.GetSafeArgument( "-opt1", 0, 100 ) );
|
||||
|
||||
// since opt2 has no arguments, just test for the presence of
|
||||
// the '-opt2' switch
|
||||
bool bOptSwitch2 = cmdLine.HasSwitch("-opt2");
|
||||
|
||||
.... and so on....
|
||||
|
||||
}
|
||||
<!-- end the block of source code -->
|
||||
</FONT></TT></PRE>
|
||||
|
||||
<!-- demo project -->
|
||||
|
||||
<p><A HREF="cmdline.zip">Download source - 5 Kb</A>
|
||||
|
||||
|
||||
<!-- Date Posted and Last update (eg August 11, 1998) -->
|
||||
<p>Date Posted: June 16, 1999
|
||||
|
||||
<!--#include virtual="footer.shtml" -->
|
||||
@@ -1,304 +0,0 @@
|
||||
/***************************************************************************
|
||||
imageconv.cpp - description
|
||||
-------------------
|
||||
begin : Die Apr 23 21:02:14 CEST 2002
|
||||
copyright : (C) 2002 by Werner Mayer
|
||||
email :
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Library General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* Werner Mayer 2002 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "imageconv.h"
|
||||
#include <QStringList>
|
||||
#include <QBuffer>
|
||||
#include <QTextStream>
|
||||
#include <QImage>
|
||||
#include <QImageWriter>
|
||||
#include <QImageReader>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
CCmdLineParser::CCmdLineParser(int argc, char** argv)
|
||||
{
|
||||
SplitLine(argc, argv);
|
||||
}
|
||||
|
||||
CCmdParam CCmdLineParser::GetArgumentList(const char* pSwitch)
|
||||
{
|
||||
if (HasSwitch(pSwitch))
|
||||
{
|
||||
CCmdLineParser::iterator theIterator;
|
||||
|
||||
theIterator = find(pSwitch);
|
||||
if (theIterator!=end())
|
||||
{
|
||||
return (*theIterator).second;
|
||||
}
|
||||
}
|
||||
|
||||
CCmdParam param;
|
||||
return param;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
QString CImageConvApp::m_Executable = "ImageConv";
|
||||
QString CImageConvApp::m_BmpFactory = "BmpFactoryIcons.cpp";
|
||||
|
||||
CImageConvApp::CImageConvApp(const QString& sFile)
|
||||
{
|
||||
m_bUpdate = false;
|
||||
m_Output = sFile;
|
||||
QString filter = "*.png;*.bmp;*.xbm;*.pnm;*.jpg;*.jpeg;*.mng;*.gif"; // not "*.xpm"!
|
||||
m_Dir.setNameFilters(filter.split(';'));
|
||||
}
|
||||
|
||||
void CImageConvApp::SetOutputFile(const QString& sFile)
|
||||
{
|
||||
m_Output = sFile;
|
||||
}
|
||||
|
||||
void CImageConvApp::SetNameFilters(const QStringList& nameFilter)
|
||||
{
|
||||
m_Dir.setNameFilters(nameFilter);
|
||||
}
|
||||
|
||||
bool CImageConvApp::Save(const QString& fn)
|
||||
{
|
||||
int iPos = fn.indexOf(".");
|
||||
|
||||
QString ext = fn.mid(iPos+1); // extension of filename
|
||||
QString name = fn.mid(0,iPos); // filename without extension
|
||||
|
||||
if (!m_clPixmap.isNull())
|
||||
{
|
||||
if (!fn.isEmpty())
|
||||
{
|
||||
return m_clPixmap.save(fn, ext.toUpper().toLatin1());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CImageConvApp::Load(const QString& fn)
|
||||
{
|
||||
QByteArray ext = QImageReader::imageFormat(fn);
|
||||
|
||||
if (!fn.isEmpty())
|
||||
return m_clPixmap.load( fn, ext);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const QPixmap& CImageConvApp::GetPixmap() const
|
||||
{
|
||||
return m_clPixmap;
|
||||
}
|
||||
|
||||
bool CImageConvApp::ConvertToXPM(bool bAppendToFile)
|
||||
{
|
||||
QStringList list = m_Dir.entryList();
|
||||
|
||||
// print to the console
|
||||
cout << "Try converting to XPM..." << endl;
|
||||
if (list.count() == 0)
|
||||
{
|
||||
cout << "Cannot find " << (const char*)m_Dir.nameFilters().join(" ").toLatin1() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (QStringList::Iterator it = list.begin(); it != list.end(); ++it)
|
||||
{
|
||||
QByteArray ext = QImageReader::imageFormat(*it);
|
||||
if (ext.isEmpty())
|
||||
continue; // no image format
|
||||
|
||||
if (m_Output == *it)
|
||||
continue; // if the file is the output file itself
|
||||
|
||||
cout << "Converting " << (const char*)(*it).toLatin1() << " ...";
|
||||
|
||||
if (Load(*it) == true)
|
||||
{
|
||||
QString name(*it);
|
||||
name.replace(name.indexOf(".")+1, 4, "xpm");
|
||||
|
||||
bool ok;
|
||||
|
||||
QFileInfo fi(*it);
|
||||
if (bAppendToFile)
|
||||
ok = AppendToFile(fi.baseName());
|
||||
else
|
||||
ok = Save(name);
|
||||
|
||||
if (ok)
|
||||
cout << "Done" << endl;
|
||||
else
|
||||
cout << "failed" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "failed" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CImageConvApp::CreateBmpFactory()
|
||||
{
|
||||
// empty file
|
||||
//
|
||||
QFileInfo fi(m_BmpFactory);
|
||||
|
||||
// already exists
|
||||
if (fi.exists() && fi.isFile())
|
||||
return;
|
||||
|
||||
QFile fw(m_BmpFactory);
|
||||
QTextStream tw (&fw);
|
||||
if (!fw.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::WriteOnly))
|
||||
return;
|
||||
|
||||
// write header stuff
|
||||
tw << "\n";
|
||||
tw << "void RegisterIcons()\n";
|
||||
tw << "{\n";
|
||||
tw << " Gui::BitmapFactoryInst& rclBmpFactory = Gui::BitmapFactory();\n";
|
||||
tw << "}\n";
|
||||
fw.close();
|
||||
}
|
||||
|
||||
bool CImageConvApp::AppendToFile(const QString& file)
|
||||
{
|
||||
CreateBmpFactory();
|
||||
|
||||
QString ohead("static char");
|
||||
QString nhead("static const char");
|
||||
|
||||
// save as XPM into tmp. buffer
|
||||
QByteArray str;
|
||||
QBuffer buf(&str);
|
||||
buf.open (QIODevice::WriteOnly);
|
||||
QImageWriter iio(&buf, "XPM");
|
||||
QImage im;
|
||||
im = m_clPixmap.toImage();
|
||||
iio.write(im);
|
||||
buf.close();
|
||||
|
||||
// convert to string and make changes
|
||||
QString txt = str;
|
||||
txt.replace(ohead, nhead);
|
||||
txt.replace(QString("dummy"), file);
|
||||
|
||||
// open file
|
||||
bool found = false;
|
||||
QFile fw(m_Output);
|
||||
if (fw.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QTextStream tr (&fw);
|
||||
QString line;
|
||||
do
|
||||
{
|
||||
line = tr.readLine();
|
||||
if ((line.indexOf(file)) != -1) // icon already registered
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
} while (!tr.atEnd() && !found);
|
||||
|
||||
fw.close();
|
||||
}
|
||||
|
||||
// register new icon
|
||||
if (!found)
|
||||
{
|
||||
if (!fw.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::ReadWrite | QIODevice::Append))
|
||||
return false;
|
||||
|
||||
// write into file now
|
||||
QTextStream tw (&fw);
|
||||
tw << txt << "\n";
|
||||
fw.close();
|
||||
|
||||
if (m_bUpdate)
|
||||
{
|
||||
QFile bmp(m_BmpFactory);
|
||||
QTextStream ts (&bmp);
|
||||
if (!bmp.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::WriteOnly))
|
||||
return false;
|
||||
|
||||
bmp.seek(bmp.size()-3);
|
||||
ts << " rclBmpFactory.addXPM(\"" << file << "\", " << file << ");\n";
|
||||
ts << "}\n";
|
||||
bmp.close();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CImageConvApp::Error()
|
||||
{
|
||||
cerr << "Usage: " << (const char*)m_Executable.toLatin1() << " [OPTION(S)] -i input file(s) {-o output file}" << endl;
|
||||
cerr << "Try '" << (const char*)m_Executable.toLatin1() << " --help' for more information." << endl;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void CImageConvApp::Version()
|
||||
{
|
||||
cerr << (const char*)m_Executable.toLatin1() << " 1.0.0 " << endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void CImageConvApp::Usage()
|
||||
{
|
||||
cerr << "Usage: " << (const char*)m_Executable.toLatin1() << " [OPTION(S)] -i input file(s) {-o output file}\n" << endl;
|
||||
cerr << "Options:" << endl;
|
||||
|
||||
cerr << " -i \tSpecify the input file(s).\n"
|
||||
" \tSeveral filenames must be separated by a blank.\n"
|
||||
" \tIf you want to select all files of a format\n"
|
||||
" \tyou also can write \"*.[FORMAT]\" (e.g. *.png).\n"
|
||||
" \tSpecifying several files only makes sense in\n"
|
||||
" \taddition with -a or -x." << endl;
|
||||
|
||||
cerr << " -o \tSpecify the output file." << endl;
|
||||
|
||||
cerr << " -x, --xpm\tConvert all specified image files to XPM.\n"
|
||||
" \tFor each specified image file a corresponding\n"
|
||||
" \tXPM file will be created.\n"
|
||||
" \tWith -i you can specify the input files." << endl;
|
||||
|
||||
cerr << " -a, --append\tConvert all specified image files to XPM and\n"
|
||||
" \tappend the result to the file specified with -o.\n"
|
||||
" \tWith -i you can specify the input files.\n" << endl;
|
||||
|
||||
|
||||
cerr << " -u, --update\tUpdate the file \"BmpFactoryIcons.cpp\"\n"
|
||||
" \tThis is a special mode to add icons to the FreeCAD's\n"
|
||||
" \tbitmap factory automatically.\n"
|
||||
" \tThis switch is only available in addition with -a.\n" << endl;
|
||||
|
||||
cerr << " -v, --version\tPrint the version and exit." << endl;
|
||||
|
||||
cerr << " -h, --help\tPrint this message and exit.\n" << endl;
|
||||
|
||||
cerr << "This program supports the following image formats:\n"
|
||||
" BMP, GIF, JPEG, MNG, PNG, PNM, XBM and XPM\n\n"
|
||||
<< (const char*)m_Executable.toLatin1() << " uses Qt Version " << qVersion() << "\n"
|
||||
"Qt can be downloaded at http://www.trolltech.com." << endl;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/***************************************************************************
|
||||
imageconv.h - description
|
||||
-------------------
|
||||
begin : Die Apr 23 21:02:14 CEST 2002
|
||||
copyright : (C) 2002 by Werner Mayer
|
||||
email :
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Library General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* Werner Mayer 2002 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef IMAGECONV_H
|
||||
#define IMAGECONV_H
|
||||
|
||||
// includes
|
||||
#include "CmdLine.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QDir>
|
||||
|
||||
// defines
|
||||
#define TString std::string
|
||||
#define TVector std::vector
|
||||
#define TMap std::map
|
||||
#define TPair std::pair
|
||||
|
||||
|
||||
// the command line parser class
|
||||
class CCmdLineParser : public CCmdLine
|
||||
{
|
||||
public:
|
||||
CCmdLineParser (int argc, char** argv);
|
||||
~CCmdLineParser () {}
|
||||
|
||||
CCmdParam GetArgumentList(const char* pSwitch);
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
class CICException
|
||||
{
|
||||
public:
|
||||
CICException(const QString& text)
|
||||
: msg(text) {}
|
||||
CICException(const CICException& e)
|
||||
{ *this = e; }
|
||||
~CICException()
|
||||
{ }
|
||||
QString what() const
|
||||
{ return msg; }
|
||||
|
||||
private:
|
||||
QString msg;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
|
||||
class CImageConvApp
|
||||
{
|
||||
public:
|
||||
CImageConvApp(const QString& sFile = "Images.cpp");
|
||||
void SetOutputFile(const QString& sFile);
|
||||
void SetNameFilters(const QStringList& nameFilter);
|
||||
bool Save(const QString& fn);
|
||||
bool Load(const QString& fn);
|
||||
bool ConvertToXPM(bool bAppendToFile = false);
|
||||
bool AppendToFile(const QString& file);
|
||||
void SetUpdateBmpFactory(bool b)
|
||||
{ m_bUpdate = b; }
|
||||
void CreateBmpFactory();
|
||||
|
||||
const QPixmap& GetPixmap() const;
|
||||
|
||||
static void Usage();
|
||||
static void Error();
|
||||
static void Version();
|
||||
|
||||
private:
|
||||
bool m_bUpdate;
|
||||
static QString m_Executable;
|
||||
static QString m_BmpFactory;
|
||||
QPixmap m_clPixmap; // pixmap
|
||||
QString m_Output; // specified output file
|
||||
QDir m_Dir; // directory
|
||||
};
|
||||
|
||||
#endif // IMAGECONV_H
|
||||
@@ -1,148 +0,0 @@
|
||||
/***************************************************************************
|
||||
main.cpp - description
|
||||
-------------------
|
||||
begin : Die Apr 23 21:02:14 CEST 2002
|
||||
copyright : (C) 2002 by Werner Mayer
|
||||
email :
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Library General Public License as *
|
||||
* published by the Free Software Foundation; either version 2 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* Werner Mayer 2002 *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <QApplication>
|
||||
#include "imageconv.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
QApplication app( argc, argv );
|
||||
CImageConvApp cICApp;
|
||||
CCmdLineParser cCmdP(argc, argv);
|
||||
|
||||
try
|
||||
{
|
||||
// look for the specified switches and arguments
|
||||
//
|
||||
//
|
||||
// show help message and exit
|
||||
if (cCmdP.HasSwitch("-h") || cCmdP.HasSwitch("--help"))
|
||||
{
|
||||
CImageConvApp::Usage();
|
||||
}
|
||||
// show version and exit
|
||||
else if (cCmdP.HasSwitch("-v") || cCmdP.HasSwitch("--version"))
|
||||
{
|
||||
CImageConvApp::Version();
|
||||
}
|
||||
|
||||
// convert all given/found image files to XPM
|
||||
if (cCmdP.HasSwitch("-x") || cCmdP.HasSwitch("--xpm"))
|
||||
{
|
||||
// search for input files
|
||||
if (cCmdP.GetArgumentCount("-i") > 0)
|
||||
{
|
||||
QStringList nameFilters;
|
||||
CCmdParam para = cCmdP.GetArgumentList("-i");
|
||||
for (TVector<TString>::iterator it = para.m_strings.begin(); it != para.m_strings.end(); it++)
|
||||
{
|
||||
cout << "Search for " << it->c_str() << endl;
|
||||
nameFilters.append(it->c_str());
|
||||
}
|
||||
|
||||
cICApp.SetNameFilters(nameFilters);
|
||||
cICApp.ConvertToXPM(false);
|
||||
}
|
||||
else
|
||||
throw CICException("No input file specified.");
|
||||
}
|
||||
|
||||
// convert all given/found image files to XPM and write the result into a text file
|
||||
else if (cCmdP.HasSwitch("-a") || cCmdP.HasSwitch("--append"))
|
||||
{
|
||||
// search for input fíles
|
||||
if (cCmdP.GetArgumentCount("-i") > 0)
|
||||
{
|
||||
cICApp.SetUpdateBmpFactory(cCmdP.HasSwitch("-a") || cCmdP.HasSwitch("--update"));
|
||||
QStringList nameFilters;
|
||||
CCmdParam para = cCmdP.GetArgumentList("-i");
|
||||
for (TVector<TString>::iterator it = para.m_strings.begin(); it != para.m_strings.end(); it++)
|
||||
{
|
||||
cout << "Search for " << it->c_str() << endl;
|
||||
nameFilters.append(it->c_str());
|
||||
}
|
||||
|
||||
cICApp.SetNameFilters(nameFilters);
|
||||
}
|
||||
else
|
||||
throw CICException("No input files specified.");
|
||||
|
||||
// search for output file
|
||||
if (cCmdP.GetArgumentCount("-o") > 0)
|
||||
{
|
||||
cICApp.SetOutputFile(QString(cCmdP.GetArgument("-o", 0).c_str()));
|
||||
cICApp.ConvertToXPM(true);
|
||||
}
|
||||
else
|
||||
throw CICException("No output file specified.");
|
||||
}
|
||||
|
||||
// convert one image file to another image file
|
||||
else if (cCmdP.HasSwitch("-i") && cCmdP.HasSwitch("-o"))
|
||||
{
|
||||
// input and output file specified
|
||||
CCmdParam p1 = cCmdP.GetArgumentList("-i");
|
||||
CCmdParam p2 = cCmdP.GetArgumentList("-o");
|
||||
|
||||
if (p1.m_strings.size() > 1)
|
||||
throw CICException("Too much input files specified.");
|
||||
if (p1.m_strings.size() < 1)
|
||||
throw CICException("No input file specified.");
|
||||
if (p2.m_strings.size() > 1)
|
||||
throw CICException("Too much output files specified.");
|
||||
if (p2.m_strings.size() < 1)
|
||||
throw CICException("No output file specified.");
|
||||
|
||||
TString fil1(*p1.m_strings.begin());
|
||||
TString fil2(*p2.m_strings.begin());
|
||||
|
||||
if (cICApp.Load(QString(fil1.c_str())) == false)
|
||||
{
|
||||
cout << "Loading of " << fil1.c_str() << " failed!" << endl;
|
||||
cout << "Perhaps the file does not exist or QT does not support this format." << endl;
|
||||
return -1;
|
||||
}
|
||||
if (cICApp.Save(QString(fil2.c_str())) == false)
|
||||
{
|
||||
cout << "Saving of " << fil2.c_str() << " failed!" << endl;
|
||||
cout << "Perhaps QT does not support this format." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Converted successfully!" << endl;
|
||||
}
|
||||
}
|
||||
// no/wrong arguments
|
||||
else
|
||||
throw CICException("Wrong arguments.");
|
||||
}
|
||||
catch(const CICException& e)
|
||||
{
|
||||
cerr << (const char*)e.what().toLatin1() << endl;
|
||||
CImageConvApp::Error();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
cerr << "An unknown exception has occurred!!!" << endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(FirstSuite, FirstTest){
|
||||
EXPECT_NE(1, 1) << "are in fact equal";
|
||||
}
|
||||
|
||||
TEST(FirstSuite, SecondTest){
|
||||
EXPECT_EQ(1, 2) << "not equal";
|
||||
}
|
||||
|
||||
TEST(FirstSuite, ThirdTest){
|
||||
ASSERT_STREQ("A", "A") << "str not equal";
|
||||
}
|
||||
TEST(FirstSuite,FifthTest){
|
||||
ASSERT_STRNE("am", "am") << "str equal";
|
||||
}
|
||||
TEST(FirstSuite, FourthTest){
|
||||
ASSERT_STREQ("am", "A") << "str not equal";
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
#include "gtest/gtest.h"
|
||||
Reference in New Issue
Block a user