mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-21 16:04:13 +02:00
Compare commits
249 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c3b0e6725e | |||
| 3f8e6418d0 | |||
| a86fe2a46b | |||
| 206edcbb7d | |||
| 0a7ea032d9 | |||
| 52713704bc | |||
| 923723a9de | |||
| ff3c2e0916 | |||
| adca07f26f | |||
| 12ecf6b28f | |||
| 1ee828da5b | |||
| 837e1e7f09 | |||
| 25962118a2 | |||
| 35275de4cc | |||
| d641b964bd | |||
| e90dddbbc6 | |||
| ce8884394a | |||
| 8606cc5328 | |||
| 60d9299d45 | |||
| c71839a291 | |||
| d9a2539702 | |||
| 22c1ec9321 | |||
| 4300a655bc | |||
| e7e2864641 | |||
| 2ed85f6fc7 | |||
| e62d43d024 | |||
| 6562498ca2 | |||
| 38e504fb7e | |||
| 4aef4d17d2 | |||
| c89243a36f | |||
| 4a83521306 | |||
| a7f406cd44 | |||
| dad6206386 | |||
| 451f8c3296 | |||
| 43a1f6a1a9 | |||
| b208a4f131 | |||
| 1c8e7ed052 | |||
| e6ffc8b622 | |||
| 9004db1d99 | |||
| edf483d88f | |||
| 0920e82188 | |||
| eba258f6cd | |||
| 2eed3acd3d | |||
| abd5e8978a | |||
| 43d27a9563 | |||
| d3424db23d | |||
| 0d722b6033 | |||
| 96fac96b89 | |||
| 1ec4f56a50 | |||
| 839324f231 | |||
| a756bc0722 | |||
| 2269a4641b | |||
| 7cd04f2a14 | |||
| c2f405c32d | |||
| 265aa44320 | |||
| 395c6f6602 | |||
| fd38f55724 | |||
| 85ed1b8a2a | |||
| 607eb4b1ea | |||
| 1e124450f2 | |||
| 4d70fcf35c | |||
| 55c2c0df9d | |||
| b94b244919 | |||
| bd6bed8d61 | |||
| 6ed26358e8 | |||
| 6a2b3973bc | |||
| d9db6e59e7 | |||
| 22469813fe | |||
| 88823ea35f | |||
| 9363e9bc2e | |||
| a5fe544415 | |||
| 9bfe18807f | |||
| 199444b6db | |||
| bdd52a0e2b | |||
| 86ce8fcd92 | |||
| 428687ee4b | |||
| 512d74c745 | |||
| 561b9c4eb1 | |||
| 00e75604b0 | |||
| ceda1e082a | |||
| ce890da342 | |||
| 2785e25569 | |||
| c8e4396b2a | |||
| 0147453494 | |||
| 181bbb7f21 | |||
| 3665ec1bcd | |||
| fcd2a4e0e0 | |||
| 3c1c29f6c3 | |||
| cafc5bcf6d | |||
| 3cbb930751 | |||
| 51209d30b6 | |||
| 9c55d36d55 | |||
| 3ac557570c | |||
| 0c2cf409f8 | |||
| 467a14df71 | |||
| 1b6768fcec | |||
| a6fd42ac5f | |||
| ce17b5c984 | |||
| b46a4cfc2a | |||
| 00d8822583 | |||
| 8edda68e96 | |||
| ad9a47602d | |||
| b034d3c5b3 | |||
| dd08b3daa5 | |||
| 2bdad43371 | |||
| c05033d44c | |||
| 15c893de89 | |||
| 3e7dd15392 | |||
| 061f07ef9e | |||
| cb0d8c8f63 | |||
| f9d063bd38 | |||
| fab5571ea2 | |||
| a0acf878a2 | |||
| 21588a9c10 | |||
| fcbea2dafd | |||
| 1272b9db06 | |||
| 6e8d821853 | |||
| e64c0618c8 | |||
| 3af551583c | |||
| b274170cff | |||
| bd7d60021c | |||
| 12f443dd89 | |||
| 9afba7091c | |||
| 3d5799773e | |||
| 9c3ab588a4 | |||
| 3a26cc4b86 | |||
| 88f5af08d7 | |||
| 29e4817254 | |||
| c8b5901296 | |||
| f8cb997f3b | |||
| 1e8f5d8a72 | |||
| ab8b85127f | |||
| 52d5c7572c | |||
| 30661c2e2d | |||
| d74317c87a | |||
| 256993e25b | |||
| b18904415e | |||
| 18477c22b5 | |||
| 128d9e8dff | |||
| 6eb5384048 | |||
| 4e9463ee8a | |||
| baa3a16614 | |||
| 32502bef2c | |||
| c13971c0fe | |||
| 4e8893929f | |||
| 59c51869b3 | |||
| f6f68871d1 | |||
| 20a0a888c7 | |||
| d2e0532b12 | |||
| a8df5e3df9 | |||
| 73250bd746 | |||
| 956836458a | |||
| 2c88f78f69 | |||
| f85ee19fc0 | |||
| 2f415117f7 | |||
| 7c0e867226 | |||
| 0b7197118a | |||
| 77f8e26ffc | |||
| 16dbc5c404 | |||
| 73f7ea8f50 | |||
| 99e9ce5aca | |||
| bc06f7d444 | |||
| 2620d34b59 | |||
| 4b675dda1b | |||
| e982778526 | |||
| 10e5cd00f4 | |||
| 6bc53277ec | |||
| 7d4cbc30f1 | |||
| 2fcf3540dd | |||
| a45a984b32 | |||
| 1f647fa229 | |||
| c4d2f0c4fb | |||
| ac47f52eb0 | |||
| d2e75b4195 | |||
| bbc995c91e | |||
| 2322e6fd12 | |||
| b5722c3f2a | |||
| 2926ca7306 | |||
| c7893c8229 | |||
| 412bc7f71f | |||
| c147e6562d | |||
| bee25a4ca9 | |||
| 6d09041dce | |||
| 1a12d440b2 | |||
| 85f46f2b48 | |||
| 9637420756 | |||
| 6c68c461b1 | |||
| c830101ba6 | |||
| a1c0907811 | |||
| ffd829bb69 | |||
| 957bbe5edb | |||
| ce0ba4a681 | |||
| 8295083f05 | |||
| a2441a6f81 | |||
| c1f9af8544 | |||
| 033c2f93a8 | |||
| 83623a0fa6 | |||
| c85f80bbcf | |||
| c6995a0e7e | |||
| f18eda845b | |||
| 73e9473db4 | |||
| 7307128fc3 | |||
| 799ff5573f | |||
| 6f2c66afef | |||
| c39c7414cf | |||
| c33f250910 | |||
| c265f0206c | |||
| cfa1e3ed27 | |||
| 36dd1624d2 | |||
| a583b3c43c | |||
| 1738c3ad6c | |||
| 82026d8f7c | |||
| a494a8fd6c | |||
| 95d7b74e9e | |||
| 68e507a522 | |||
| 6657b3de2b | |||
| 4c038a868b | |||
| dab4c6c424 | |||
| 6208c7e5df | |||
| 31feb7b7b0 | |||
| 622791f994 | |||
| 02e6eceb65 | |||
| 7c941e4697 | |||
| a48124a27a | |||
| e19d60ae55 | |||
| 030e6ebf00 | |||
| b855d760a8 | |||
| 5b8d05fc1e | |||
| b034b1a634 | |||
| 44ed01ff5d | |||
| 6061c63809 | |||
| 884ec4bbb9 | |||
| 9285d12333 | |||
| fb0649ceee | |||
| 6f9f5f84c2 | |||
| 5dbb9f28de | |||
| c26cf34397 | |||
| c6e7c5d371 | |||
| 7347322221 | |||
| c23999acd1 | |||
| 7afc1eb56b | |||
| 0c2027fd77 | |||
| f9cbf2365d | |||
| 52992b31eb | |||
| d7c75ea5a5 | |||
| b9153269a4 | |||
| eab9603d8a | |||
| e7cbb8f50e | |||
| e3d11a4992 |
@@ -56,6 +56,7 @@ jobs:
|
||||
mingw-w64-ucrt-x86_64-extra-cmake-modules
|
||||
mingw-w64-ucrt-x86_64-nsis
|
||||
mingw-w64-ucrt-x86_64-angleproject
|
||||
mingw-w64-ucrt-x86_64-qt6-declarative
|
||||
|
||||
- name: Cache ccache
|
||||
uses: actions/cache@v5
|
||||
@@ -217,10 +218,71 @@ jobs:
|
||||
cp -r "$GITHUB_WORKSPACE/examples" "$FILES/examples" || true
|
||||
cp -r "$GITHUB_WORKSPACE/fonts" "$FILES/fonts" || true
|
||||
|
||||
cp -r "$GITHUB_WORKSPACE/lang" "$FILES/lang" || true
|
||||
find "$GITHUB_WORKSPACE/build" -name "*.qm" -exec cp {} "$FILES/lang/" \; 2>/dev/null || true
|
||||
echo "=== .qm files in files/lang/ ==="
|
||||
ls "$FILES/lang/"*.qm 2>/dev/null | wc -l || echo "0 .qm files"
|
||||
# --- Translations ---
|
||||
# Since PR #751 the .qm files are no longer tracked in git: lrelease
|
||||
# generates them in build/lang/ (OUTPUT_LOCATION "lang", relative to
|
||||
# the build dir). Expected set = the .ts listed in TS_FILES
|
||||
# (cmake/qet_compilation_vars.cmake): a missing .qm fails the job
|
||||
# instead of silently shipping an untranslated build; a .ts present
|
||||
# in lang/ but not listed in TS_FILES only raises a warning.
|
||||
# find/grep only, no shell glob: $GITHUB_WORKSPACE is a Windows path
|
||||
# (D:\a\...) and its backslashes break glob patterns.
|
||||
QM_SRC="$GITHUB_WORKSPACE/build/lang"
|
||||
mkdir -p "$FILES/lang"
|
||||
TS_LISTED=$(grep -o 'lang/qet_[A-Za-z_]*\.ts' "$GITHUB_WORKSPACE/cmake/qet_compilation_vars.cmake" \
|
||||
| sed -e 's#^lang/##' -e 's#\.ts$##' | LC_ALL=C sort -u || true)
|
||||
[ -n "$TS_LISTED" ] || { echo "ERROR: cannot read TS_FILES from cmake/qet_compilation_vars.cmake"; exit 1; }
|
||||
TS_PRESENT=$(find "$GITHUB_WORKSPACE/lang" -maxdepth 1 -name 'qet_*.ts' -exec basename {} .ts \; | LC_ALL=C sort)
|
||||
UNLISTED=$(LC_ALL=C comm -13 <(echo "$TS_LISTED") <(echo "$TS_PRESENT"))
|
||||
if [ -n "$UNLISTED" ]; then
|
||||
echo "::warning::.ts files not in TS_FILES, no .qm built:" $UNLISTED
|
||||
fi
|
||||
find "$QM_SRC" -maxdepth 1 -name 'qet_*.qm' -exec cp {} "$FILES/lang/" \; 2>/dev/null || true
|
||||
QM_PRESENT=$(find "$FILES/lang" -maxdepth 1 -name 'qet_*.qm' -exec basename {} .qm \; | LC_ALL=C sort)
|
||||
MISSING=$(LC_ALL=C comm -23 <(echo "$TS_LISTED") <(echo "$QM_PRESENT"))
|
||||
QM_COUNT=$(printf '%s\n' "$QM_PRESENT" | grep -c . || true)
|
||||
TS_COUNT=$(printf '%s\n' "$TS_LISTED" | grep -c .)
|
||||
echo "=== $QM_COUNT .qm files copied to files/lang/ (expected: $TS_COUNT) ==="
|
||||
if [ -n "$MISSING" ]; then
|
||||
echo "ERROR: missing translations:" $MISSING
|
||||
find "$GITHUB_WORKSPACE/build" -name '*.qm' || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Qt's own translations (OK/Cancel buttons, standard dialogs...):
|
||||
# they come from qtbase_XX.qm, not from QET's .ts, and windeployqt
|
||||
# runs with --no-translations. QETApp::setLanguage() falls back to
|
||||
# lang/qt_XX.qm, so copy each qtbase_XX.qm there under that name
|
||||
# (qtbase_XX.qm is standalone, unlike Qt's qt_XX.qm meta catalogs).
|
||||
QT_TR_DIR=/ucrt64/share/qt6/translations
|
||||
if [ ! -d "$QT_TR_DIR" ]; then
|
||||
QT_TR_DIR=$(cygpath -u "$(/ucrt64/bin/qtpaths6 --query QT_INSTALL_TRANSLATIONS 2>/dev/null)" 2>/dev/null || true)
|
||||
fi
|
||||
find "$QT_TR_DIR" -maxdepth 1 -name 'qtbase_*.qm' 2>/dev/null | while read -r f; do
|
||||
l=$(basename "$f" .qm)
|
||||
cp "$f" "$FILES/lang/qt_${l#qtbase_}.qm"
|
||||
done
|
||||
# QET languages Qt only ships with a region (pt -> pt_PT, zh -> zh_CN):
|
||||
# QTranslator only shortens codes (fr_FR -> fr), it never extends them.
|
||||
for q in $TS_LISTED; do
|
||||
l=${q#qet_}
|
||||
if [ ! -e "$FILES/lang/qt_$l.qm" ]; then
|
||||
if [ -e "$QT_TR_DIR/qtbase_${l}_${l^^}.qm" ]; then
|
||||
alt="$QT_TR_DIR/qtbase_${l}_${l^^}.qm"
|
||||
else
|
||||
alt=$(find "$QT_TR_DIR" -maxdepth 1 -name "qtbase_${l}_*.qm" 2>/dev/null | LC_ALL=C sort | head -1 || true)
|
||||
fi
|
||||
if [ -n "$alt" ]; then
|
||||
cp "$alt" "$FILES/lang/qt_$l.qm"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
QT_QM_COUNT=$(find "$FILES/lang" -maxdepth 1 -name 'qt_*.qm' | wc -l)
|
||||
echo "=== $QT_QM_COUNT Qt translation files (qt_*.qm) copied from $QT_TR_DIR ==="
|
||||
if [ "$QT_QM_COUNT" -eq 0 ]; then
|
||||
echo "ERROR: no qtbase_*.qm found in '$QT_TR_DIR' (mingw-w64-ucrt-x86_64-qt6-translations installed?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for f in LICENSE ChangeLog CREDIT README ELEMENTS.LICENSE; do
|
||||
cp "$GITHUB_WORKSPACE/$f" "$FILES/$f" 2>/dev/null || true
|
||||
|
||||
@@ -7,3 +7,4 @@ doc/*
|
||||
!doc/QElectroTech.qch
|
||||
QElectroTech.tag
|
||||
!doc/doc-utils
|
||||
lang/*.qm
|
||||
|
||||
+81
-100
@@ -19,7 +19,7 @@ include(cmake/hoto_update_cmake_message.cmake)
|
||||
cmake_minimum_required(VERSION 3.5...4.2)
|
||||
|
||||
project(qelectrotech
|
||||
VERSION 0.100.1
|
||||
VERSION 0.200.1
|
||||
DESCRIPTION "QET is a CAD/CAE editor focusing on schematics drawing features."
|
||||
HOMEPAGE_URL "https://qelectrotech.org/"
|
||||
LANGUAGES C CXX)
|
||||
@@ -28,25 +28,6 @@ include(cmake/copyright_message.cmake)
|
||||
|
||||
set(QET_DIR ${PROJECT_SOURCE_DIR})
|
||||
|
||||
# QT_VERSION_MAJOR is chosen explicitly by whoever configures the build,
|
||||
# via -DQT_VERSION_MAJOR=5 or -DQT_VERSION_MAJOR=6.
|
||||
# Default to Qt5 (current stable) when not specified, so existing
|
||||
# CI/scripts that don't pass this option keep working unchanged.
|
||||
# This must happen BEFORE add_subdirectory(tests) and the fetch_*.cmake
|
||||
# includes below, so every subdirectory and every FetchContent dependency
|
||||
# sees a consistent, already-defined value.
|
||||
if(NOT DEFINED QT_VERSION_MAJOR)
|
||||
set(QT_VERSION_MAJOR 5)
|
||||
endif()
|
||||
|
||||
# Some third-party CMake projects we pull in via FetchContent (e.g.
|
||||
# SingleApplication) don't know about QET_VERSION_MAJOR: they follow Qt's
|
||||
# own "QT_DEFAULT_MAJOR_VERSION" convention instead, and silently default
|
||||
# to Qt5 if it isn't set. Propagate our choice so they stay in sync,
|
||||
# otherwise they can end up linked against a different Qt major version
|
||||
# than the rest of QET, which breaks AUTOMOC with an
|
||||
# INTERFACE_QT_MAJOR_VERSION mismatch at generate time.
|
||||
set(QT_DEFAULT_MAJOR_VERSION ${QT_VERSION_MAJOR} CACHE STRING "Qt version to use (5 or 6)" FORCE)
|
||||
|
||||
include(cmake/paths_compilation_installation.cmake)
|
||||
include(cmake/start_options.cmake)
|
||||
@@ -65,7 +46,7 @@ SET(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(
|
||||
Qt${QT_VERSION_MAJOR}
|
||||
Qt6
|
||||
COMPONENTS
|
||||
${QET_COMPONENTS}
|
||||
REQUIRED)
|
||||
@@ -76,12 +57,9 @@ find_package(
|
||||
# and only provide the implicit Qt6::GuiPrivate target created alongside
|
||||
# Qt6::Gui. Try the component quietly, then verify the target below so a
|
||||
# missing private-headers package fails here instead of at compile time.
|
||||
# Qt5 has no such component as its GuiPrivate target always exists once Gui is found.
|
||||
if(QT_VERSION_MAJOR GREATER_EQUAL 6)
|
||||
find_package(Qt6 QUIET COMPONENTS GuiPrivate)
|
||||
endif()
|
||||
find_package(Qt6 QUIET COMPONENTS GuiPrivate)
|
||||
|
||||
if(QT_VERSION_MAJOR GREATER_EQUAL 6 AND NOT TARGET Qt6::GuiPrivate)
|
||||
if(NOT TARGET Qt6::GuiPrivate)
|
||||
message(FATAL_ERROR
|
||||
"Qt6::GuiPrivate was not found. It is required for PDF hyperlink "
|
||||
"support (<private/qpdf_p.h>). Install the Qt6 private headers "
|
||||
@@ -98,15 +76,29 @@ endif()
|
||||
# see the QT_VERSION_CHECK / QET_HAS_QTPDF guards in diagrameventaddpdf.*
|
||||
# and pdfpagesdialog.*.
|
||||
set(QET_HAS_QTPDF FALSE)
|
||||
if(QT_VERSION_MAJOR GREATER_EQUAL 6)
|
||||
find_package(Qt6 QUIET COMPONENTS Pdf)
|
||||
if(TARGET Qt6::Pdf AND NOT Qt6_VERSION VERSION_LESS 6.4.0)
|
||||
set(QET_HAS_QTPDF TRUE)
|
||||
list(APPEND QET_PRIVATE_LIBRARIES Qt::Pdf)
|
||||
add_compile_definitions(QET_HAS_QTPDF)
|
||||
else()
|
||||
message(STATUS "QtPdf module not available (or Qt < 6.4): PDF page import feature disabled")
|
||||
endif()
|
||||
find_package(Qt6 QUIET COMPONENTS Pdf)
|
||||
if(TARGET Qt6::Pdf AND NOT Qt6_VERSION VERSION_LESS 6.4.0)
|
||||
set(QET_HAS_QTPDF TRUE)
|
||||
list(APPEND QET_PRIVATE_LIBRARIES Qt::Pdf)
|
||||
add_compile_definitions(QET_HAS_QTPDF)
|
||||
else()
|
||||
message(STATUS "QtPdf module not available (or Qt < 6.4): PDF page import feature disabled")
|
||||
endif()
|
||||
|
||||
# JavaScript scripting (bugtracker #162: `--run script.js`, and later a
|
||||
# "Run Script..." menu action) needs QJSEngine, in the Qml module. As with
|
||||
# QtPdf above, this is not fatal when missing: some minimal Qt6 packagings
|
||||
# may not ship it, and scripting is optional functionality nothing else in
|
||||
# the application depends on. When it's missing the feature is silently
|
||||
# disabled - see the QET_HAS_SCRIPTING guard in qetscripting.*.
|
||||
set(QET_HAS_SCRIPTING FALSE)
|
||||
find_package(Qt${QT_VERSION_MAJOR} QUIET COMPONENTS Qml)
|
||||
if(TARGET Qt${QT_VERSION_MAJOR}::Qml)
|
||||
set(QET_HAS_SCRIPTING TRUE)
|
||||
list(APPEND QET_PRIVATE_LIBRARIES Qt::Qml)
|
||||
add_compile_definitions(QET_HAS_SCRIPTING)
|
||||
else()
|
||||
message(STATUS "Qt Qml module not available: JavaScript scripting (--run) disabled")
|
||||
endif()
|
||||
|
||||
find_package(SQLite3 REQUIRED)
|
||||
@@ -123,17 +115,13 @@ endif()
|
||||
|
||||
set(CMAKE_AUTOUIC_SEARCH_PATHS ${QET_DIR}/sources/ui)
|
||||
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
set(KF_MAJOR_VERSION 6)
|
||||
else()
|
||||
set(KF_MAJOR_VERSION 5)
|
||||
endif()
|
||||
include(cmake/fetch_kdeaddons.cmake)
|
||||
|
||||
# Add sub directories
|
||||
option(PACKAGE_TESTS "Build the tests" ON)
|
||||
if(PACKAGE_TESTS)
|
||||
message("Add sub directory tests")
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -163,7 +151,22 @@ else()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE TRUE)
|
||||
# CFBundleIdentifier must not be empty. CMake's default Info.plist
|
||||
# template fills it from MACOSX_BUNDLE_GUI_IDENTIFIER; with that unset
|
||||
# the bundle ships an empty identifier, LaunchServices never registers
|
||||
# the .app, and AppKit's open/save panel service (which is keyed on the
|
||||
# client's bundle id) silently presents nothing -- every
|
||||
# QFileDialog::getOpenFileName()/getSaveFileName() call returns an empty
|
||||
# string without a panel ever appearing, so File > Open and File > Save
|
||||
# as do nothing at all.
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "org.qelectrotech.QElectroTech"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "QElectroTech"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}"
|
||||
MACOSX_BUNDLE_COPYRIGHT "Copyright 2006-2026 The QElectroTech Team"
|
||||
)
|
||||
endif()
|
||||
|
||||
# The default build only compiles the tracked .ts files to .qm (lrelease).
|
||||
@@ -174,73 +177,21 @@ endif()
|
||||
# fail with "Premature end of document".
|
||||
set_source_files_properties(
|
||||
${TS_FILES}
|
||||
PROPERTIES OUTPUT_LOCATION "${QET_DIR}/lang"
|
||||
PROPERTIES OUTPUT_LOCATION "lang"
|
||||
)
|
||||
if(QT_VERSION_MAJOR EQUAL 6)
|
||||
if(Qt6_VERSION VERSION_LESS "6.2")
|
||||
# Qt 6.0–6.1
|
||||
qt6_add_translation(QM_FILES ${TS_FILES})
|
||||
if(Qt6_VERSION VERSION_LESS "6.2")
|
||||
# Qt 6.0–6.1
|
||||
qt6_add_translation(QM_FILES ${TS_FILES})
|
||||
|
||||
# qt6_add_translation() only creates custom commands. Something must
|
||||
# depend on their outputs for them to run during the default build.
|
||||
add_custom_target(${PROJECT_NAME}_lrelease ALL
|
||||
DEPENDS ${QM_FILES}
|
||||
)
|
||||
|
||||
add_custom_target(update_translations
|
||||
COMMAND
|
||||
$<TARGET_FILE:Qt6::lupdate>
|
||||
"${CMAKE_SOURCE_DIR}/sources"
|
||||
-ts ${TS_FILES}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT
|
||||
"Updating .ts files from sources/ (lupdate) - developer target"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
elseif(Qt6_VERSION VERSION_LESS "6.7")
|
||||
# Qt 6.2–6.6: old target-based signature
|
||||
qt_add_lrelease(
|
||||
${PROJECT_NAME}
|
||||
TS_FILES ${TS_FILES}
|
||||
QM_FILES_OUTPUT_VARIABLE QM_FILES
|
||||
)
|
||||
|
||||
# Automatically creates the update_translations umbrella target.
|
||||
qt_add_lupdate(
|
||||
${PROJECT_NAME}
|
||||
TS_FILES ${TS_FILES}
|
||||
)
|
||||
|
||||
else()
|
||||
# Qt 6.7+: new signature
|
||||
qt_add_lrelease(
|
||||
TS_FILES ${TS_FILES}
|
||||
LRELEASE_TARGET ${PROJECT_NAME}_lrelease
|
||||
QM_FILES_OUTPUT_VARIABLE QM_FILES
|
||||
)
|
||||
|
||||
qt_add_lupdate(
|
||||
SOURCE_TARGETS ${PROJECT_NAME}
|
||||
TS_FILES ${TS_FILES}
|
||||
LUPDATE_TARGET update_translations
|
||||
NO_GLOBAL_TARGET
|
||||
)
|
||||
endif()
|
||||
|
||||
else()
|
||||
# Qt 5
|
||||
qt5_add_translation(QM_FILES ${TS_FILES})
|
||||
|
||||
# Likewise, qt5_add_translation() needs a target depending on its outputs,
|
||||
# unless QM_FILES are already consumed elsewhere.
|
||||
# qt6_add_translation() only creates custom commands. Something must
|
||||
# depend on their outputs for them to run during the default build.
|
||||
add_custom_target(${PROJECT_NAME}_lrelease ALL
|
||||
DEPENDS ${QM_FILES}
|
||||
)
|
||||
|
||||
add_custom_target(update_translations
|
||||
COMMAND
|
||||
$<TARGET_FILE:Qt5::lupdate>
|
||||
$<TARGET_FILE:Qt6::lupdate>
|
||||
"${CMAKE_SOURCE_DIR}/sources"
|
||||
-ts ${TS_FILES}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
@@ -248,8 +199,38 @@ else()
|
||||
"Updating .ts files from sources/ (lupdate) - developer target"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
elseif(Qt6_VERSION VERSION_LESS "6.7")
|
||||
# Qt 6.2–6.6: old target-based signature
|
||||
qt_add_lrelease(
|
||||
${PROJECT_NAME}
|
||||
TS_FILES ${TS_FILES}
|
||||
QM_FILES_OUTPUT_VARIABLE QM_FILES
|
||||
)
|
||||
|
||||
# Automatically creates the update_translations umbrella target.
|
||||
qt_add_lupdate(
|
||||
${PROJECT_NAME}
|
||||
TS_FILES ${TS_FILES}
|
||||
)
|
||||
|
||||
else()
|
||||
# Qt 6.7+: new signature
|
||||
qt_add_lrelease(
|
||||
TS_FILES ${TS_FILES}
|
||||
LRELEASE_TARGET ${PROJECT_NAME}_lrelease
|
||||
QM_FILES_OUTPUT_VARIABLE QM_FILES
|
||||
)
|
||||
|
||||
qt_add_lupdate(
|
||||
SOURCE_TARGETS ${PROJECT_NAME}
|
||||
TS_FILES ${TS_FILES}
|
||||
LUPDATE_TARGET update_translations
|
||||
NO_GLOBAL_TARGET
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# Optional precompiled headers -- see QET_ENABLE_PCH in
|
||||
# cmake/developer_options.cmake for what this trades away.
|
||||
#
|
||||
|
||||
@@ -48,7 +48,7 @@ PROJECT_NAME = QElectroTech
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = " 0.100.0-dev"
|
||||
PROJECT_NUMBER = " 0.200.1"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
+17
-13
@@ -1,3 +1,20 @@
|
||||
[ca]
|
||||
La col·lecció d'elements que s'inclou amb QElectrotech es proporciona tal com és
|
||||
i sense cap garantia que sigui adequada per al vostre ús o que funcioni correctament.
|
||||
L'ús, la modificació i la integració d'aquests elements en esquemes elèctrics
|
||||
estan permesos sense restriccions, independentment de la llicència final que regeixi
|
||||
els esquemes.
|
||||
No es permet utilitzar aquest programari ni cap fitxer associat
|
||||
com a dades de mostra per crear models d'aprenentatge automàtic.
|
||||
|
||||
Si redistribuïu la totalitat o una part de la col·lecció QElectroTech,
|
||||
amb o sense modificacions, fora d'un esquema elèctric, heu de complir
|
||||
les condicions de la llicència CC-BY:
|
||||
Aquesta obra està subjecta a la llicència Reconeixement 3.0,
|
||||
disponible en línia a http://creativecommons.org/licenses/by/3.0/ o bé
|
||||
sol·licitant-la per correu a Creative Commons, 171 Second Street, Suite 300, San Francisco,
|
||||
Califòrnia 94105, EUA.
|
||||
|
||||
[en]
|
||||
The elements collection provided along with QElectroTech is provided as is and
|
||||
without any warranty of fitness for your purpose or working.
|
||||
@@ -96,19 +113,6 @@ Para ver una copia de esta licencia, visite
|
||||
http://creativecommons.org/licenses/by/3.0/ o envie una carta a Creative
|
||||
Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.
|
||||
|
||||
[ca]
|
||||
La col·lecció de símbols QElectrotech és distribuïda tal qual i sense cap
|
||||
garantia d'idoneïtat d'ús ni de funcionament.
|
||||
Es permet incondicionalment, amb independència de la llicència final, emprar,
|
||||
editar, i incloure aquests símbols en esquemes elèctrics.
|
||||
Si vostè redistribueix una part de la col·lecció de QElectrotech o tota ella,
|
||||
amb condicions o sense, separadament d'un esquema elèctric, haurà de respectar
|
||||
les condicions de la llicència CC-BY:
|
||||
Aquesta obra es troba sota una llicència Reconeixement 3.0 de Creative Commons.
|
||||
Per veure una còpia d'aquesta llicència visiti
|
||||
http://creativecommons.org/licenses/by/3.0/ o enviï una carta a Creative
|
||||
Commons, 171 Second Street, Suite 300, San Francisco, California 94105,
|
||||
|
||||
[cs]
|
||||
Sbírka prvků poskytovaná společně s QElectroTechem je poskytována tak, jak je,
|
||||
bez záruky nebo vhodnosti pro váš účal nebo práci.
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
[Qt6 / CMake]
|
||||
Building the Qt6 line with CMake additionally requires the private
|
||||
development headers of QtGui. On Debian/Ubuntu these live in a separate
|
||||
package that is NOT pulled in by qt6-base-dev:
|
||||
|
||||
apt install qt6-base-private-dev
|
||||
|
||||
(other distributions: install your Qt 6 "private headers" development
|
||||
package, e.g. qt6-qtbase-private-devel on Fedora)
|
||||
|
||||
QET needs the private QtGui API (QPdfEngine) for clickable hyperlinks in
|
||||
the PDF export. Without the package, find_package(Qt6 ... GuiPrivate)
|
||||
succeeds but CMake later fails at generate time with:
|
||||
"Imported target Qt6::GuiPrivate includes non-existent path".
|
||||
|
||||
[ca]
|
||||
Dependències:
|
||||
libQt5 (paquets libqt5*)
|
||||
cupsys-bsd per imprimir
|
||||
|
||||
Com compilar:
|
||||
$ qmake (qmake-qt5 pels sistemes basats en Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[en]
|
||||
Requirements :
|
||||
libQt5 (see packages libqt5*)
|
||||
cupsys-bsd for printing
|
||||
|
||||
Howto compile :
|
||||
$ qmake (qmake-qt5 for Debian-based systems)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[fr]
|
||||
Pré-requis :
|
||||
libQt5 (paquets libqt5*)
|
||||
cupsys-bsd pour l'impression
|
||||
|
||||
Comment compiler :
|
||||
$ qmake (qmake-qt5 pour les systèmes basés sur Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[de]
|
||||
Abhängigkeiten:
|
||||
libQt5 (Pakete libqt5*)
|
||||
cupsys-bsd zum Drucken
|
||||
|
||||
Kompilieren:
|
||||
$ qmake (qmake-qt5 für Debian-basierende Systeme)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[ru]
|
||||
Зависимости:
|
||||
libQt5 (пакет libqt5*)
|
||||
cupsys-bsd для печати
|
||||
|
||||
Как компилировать?:
|
||||
$ qmake (qmake-qt5 для систем основанных на Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[pt]
|
||||
Dependências:
|
||||
libQt5 (ver pacotes libqt5*)
|
||||
cupsys-bsd para impressão
|
||||
|
||||
Como compilar:
|
||||
$ qmake (qmake-qt5 para sistemas baseados em Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[es]
|
||||
Dependencias:
|
||||
libQt5 (paquetes libqt5*)
|
||||
cupsys-bsd para imprimir
|
||||
|
||||
Cómo compilar:
|
||||
$ qmake (qmake-qt5 para los sistemas basados en Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[cs]
|
||||
Požadavky :
|
||||
libQt5 (viz balíček libqt5*)
|
||||
cupsys-bsd kvůli tisku
|
||||
|
||||
Jak program sestavit :
|
||||
$ qmake (qmake-qt5 u systémů založených na Debianu)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[pl]
|
||||
Zależności:
|
||||
libQt5 (pakiety libqt5 *)
|
||||
cupsys-bsd do druku
|
||||
|
||||
Sposób kompilacji:
|
||||
$ qmake (qmake-qt5 dla systemów opartych na Debianie)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[it]
|
||||
Dipendenze:
|
||||
libQt5 (vedi pacchetti libqt5*)
|
||||
cupsys-bsd per la stampa
|
||||
|
||||
Come compilare:
|
||||
$ qmake (qmake-qt5 per sistemi basati su Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[el]
|
||||
Απαιτήσεις:
|
||||
libQt5 (δείτε για πακέτα libqt5*)
|
||||
cupsys-bsd για εκτύπωση
|
||||
|
||||
Πως να το μεταγλωττίσετε:
|
||||
$ qmake (qmake-qt5 για συστήματα βασισμένα σε Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[nl]
|
||||
vereisten:
|
||||
libqt5 (zie pakketten libqt5 *)
|
||||
cupsys-bsd om af te drukken
|
||||
|
||||
Hoe te compileren:
|
||||
$ Qmake (qmake-qt5 voor Debian-gebaseerde systemen)
|
||||
$ make
|
||||
# Umask 0022
|
||||
# Make install
|
||||
|
||||
[be]
|
||||
Vereisten:
|
||||
libQt5 (pakketten libqt5*)
|
||||
cupsys-bsd voor het afdrukken
|
||||
|
||||
Hoe te compileren :
|
||||
$ qmake (qmake-qt5 voor systemen op basis van Debian)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[da]
|
||||
Krav:
|
||||
libQt5 (se pakke libqt5*)
|
||||
cupsys-bsd til udskrivning
|
||||
|
||||
Hvordan man kompilerer:
|
||||
$ qmake (qmake-qt5 for Debian baserede systemer)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
|
||||
[ja]
|
||||
必要条件 :
|
||||
libQt5 (パッケージ libqt5* を参照)
|
||||
cupsys-bsd 印刷用
|
||||
|
||||
コンパイルの方法 :
|
||||
$ qmake (Debian ベースのシステムでは qmake-qt5)
|
||||
$ make
|
||||
# umask 0022
|
||||
# make install
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
# Building QElectroTech from source
|
||||
|
||||
QElectroTech is built with **CMake** and requires the **current Qt6 only**; Qt5 and the
|
||||
old `qmake`-based build described in earlier versions of this file have
|
||||
been retired.
|
||||
|
||||
## 1. Getting the source
|
||||
|
||||
QET uses git submodules, so clone recursively:
|
||||
|
||||
```sh
|
||||
git clone --recursive https://github.com/qelectrotech/qelectrotech-source-mirror.git
|
||||
cd qelectrotech-source-mirror
|
||||
```
|
||||
|
||||
If you already have a non-recursive clone:
|
||||
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## 2. Requirements
|
||||
|
||||
| Component | Status | Notes |
|
||||
|---|---|---|
|
||||
| CMake ≥ 3.5 | required | CMake 4.3+ is also fine, see note below |
|
||||
| C++17 compiler | required | GCC or Clang on Unix-like platforms; MSVC or MinGW-w64 g++ on Windows — see [Choosing a compiler](#3-choosing-a-compiler-unix) / [Building on Windows](#6-building-on-windows-msvc--mingw) |
|
||||
| Qt6 base + widgets | required | |
|
||||
| Qt6 **GuiPrivate** headers | required | needed for clickable PDF hyperlinks; **hard build failure** at CMake generate time if missing, see below |
|
||||
| SQLite3 | required | used by the nomenclature/summary database |
|
||||
| Qt Linguist tools (`lrelease`) | required | compiles the tracked `.ts` files into `.qm` as part of every normal build |
|
||||
| pugixml | handled automatically | fetched and built via CMake FetchContent if not already present on the system — see [pugixml](#8-pugixml) below |
|
||||
| Qt Test module | required if building tests | `PACKAGE_TESTS` is `ON` by default; QtTest ships as part of the base Qt6 dev packages listed below on every platform, no extra package needed |
|
||||
| KDE Frameworks (KF6) | optional | see [Building without KDE Frameworks](#9-building-without-kde-frameworks) |
|
||||
| QtPdf module | optional | see [PDF page import](#7-pdf-page-import-qtpdf) |
|
||||
|
||||
A note on CMake versions: the project declares a minimum of 3.5 but is
|
||||
routinely built with much newer releases; if your CMake is older than 4.3 it
|
||||
simply won't have the newer `SQLite3::SQLite3` target name, which the build
|
||||
script compensates for automatically. There is nothing you need to do either
|
||||
way.
|
||||
|
||||
## 3. Building (out-of-source build)
|
||||
|
||||
Always build in a separate directory from the source tree — in-source builds
|
||||
are not supported.
|
||||
|
||||
```sh
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . --parallel
|
||||
```
|
||||
|
||||
For a Unix-like platform you'll usually also want an explicit build type,
|
||||
since CMake's default (empty) build type means no optimization and no
|
||||
debug info either:
|
||||
|
||||
```sh
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
```
|
||||
|
||||
To install (default prefix is `/usr/local`; adjust with
|
||||
`-DCMAKE_INSTALL_PREFIX=...` at the configure step if needed):
|
||||
|
||||
```sh
|
||||
sudo cmake --install .
|
||||
```
|
||||
|
||||
Useful configure-time options (pass as `-D<OPTION>=ON/OFF`):
|
||||
|
||||
| Option | Default | Effect |
|
||||
|---|---|---|
|
||||
| `PACKAGE_TESTS` | `ON` | build the test suite (needs the Qt Test module) |
|
||||
| `BUILD_WITH_KF` | distro-dependent | build against KDE Frameworks; see below |
|
||||
| `QET_ENABLE_PCH` | `OFF` | precompiled headers for faster rebuilds (needs CMake ≥ 3.16) |
|
||||
|
||||
## 3.1 Choosing a compiler (Unix)
|
||||
|
||||
Both **GCC** and **Clang** are supported on Unix-like platforms; any
|
||||
reasonably recent release with solid C++17 support works. Neither is
|
||||
hard-coded — CMake picks up whichever `cc`/`c++` (or `CC`/`CXX` environment
|
||||
variables) resolve to by default, and you can force one explicitly at
|
||||
configure time:
|
||||
|
||||
```sh
|
||||
cmake .. -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
# or
|
||||
cmake .. -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
|
||||
```
|
||||
|
||||
or equivalently, by exporting `CC`/`CXX` before calling `cmake`. The
|
||||
per-distro package lists below install GCC by default (via
|
||||
`build-essential`/`gcc-c++`/the base toolchain); see each section for the
|
||||
Clang alternative.
|
||||
|
||||
## 4. Distribution packages
|
||||
|
||||
Exact package names vary by release/branch; if a name below doesn't resolve,
|
||||
search your package manager (`apt search`, `pkg search`, `brew search`) for
|
||||
the closest match.
|
||||
|
||||
### Debian / Ubuntu
|
||||
|
||||
```sh
|
||||
sudo apt install \
|
||||
build-essential cmake ninja-build git \
|
||||
qt6-base-dev qt6-base-private-dev qt6-tools-dev qt6-tools-dev-tools \
|
||||
libsqlite3-dev \
|
||||
libkf6coreaddons-dev libkf6widgetsaddons-dev
|
||||
```
|
||||
|
||||
`qt6-base-private-dev` is **not** pulled in automatically by `qt6-base-dev`
|
||||
but is mandatory for the build (see
|
||||
[Qt6 private headers](#6-qt6-private-headers-mandatory) below).
|
||||
|
||||
For Clang instead of GCC:
|
||||
|
||||
```sh
|
||||
sudo apt install clang
|
||||
```
|
||||
|
||||
Optional, for PDF page import:
|
||||
|
||||
```sh
|
||||
sudo apt install libqt6pdf6-dev
|
||||
```
|
||||
|
||||
Optional, to use a system pugixml instead of letting CMake fetch it:
|
||||
|
||||
```sh
|
||||
sudo apt install libpugixml-dev
|
||||
```
|
||||
|
||||
### Fedora / RHEL
|
||||
|
||||
```sh
|
||||
sudo dnf install \
|
||||
cmake gcc-c++ git \
|
||||
qt6-qtbase-devel qt6-qtbase-private-devel qt6-qttools-devel \
|
||||
sqlite-devel \
|
||||
kf6-kcoreaddons-devel kf6-kwidgetsaddons-devel
|
||||
```
|
||||
|
||||
For Clang instead of GCC: `sudo dnf install clang`.
|
||||
|
||||
Optional, for PDF page import: `qt6-qtwebengine-devel` provides `QtPdf` on
|
||||
some Fedora releases — check `dnf provides '*/QPdfDocument'` if unsure.
|
||||
|
||||
Optional, for a system pugixml: `sudo dnf install pugixml-devel`.
|
||||
|
||||
### FreeBSD
|
||||
|
||||
```sh
|
||||
pkg install \
|
||||
cmake git \
|
||||
qt6-base qt6-tools \
|
||||
sqlite3 \
|
||||
kf6-kcoreaddons kf6-kwidgetsaddons
|
||||
```
|
||||
|
||||
(from ports: `devel/qt6-base`, `devel/qt6-tools`, `databases/sqlite3`,
|
||||
`devel/kf6-kcoreaddons`, `x11-toolkits/kf6-kwidgetsaddons`.) Qt6's
|
||||
`GuiPrivate` headers ship as part of `qt6-base` on FreeBSD, no separate
|
||||
package is needed. `QtPdf` is not packaged on FreeBSD at the time of writing
|
||||
— PDF page import will simply be disabled (see below).
|
||||
|
||||
Clang is the FreeBSD base system compiler and needs nothing extra; GCC is
|
||||
available via `pkg install gcc` if you'd rather use it.
|
||||
|
||||
Optional, for a system pugixml: `pkg install pugixml` (`devel/pugixml`).
|
||||
|
||||
### macOS
|
||||
|
||||
Using [Homebrew](https://brew.sh):
|
||||
|
||||
```sh
|
||||
brew install cmake qt sqlite ninja
|
||||
```
|
||||
|
||||
Homebrew's `qt` formula is Qt6 and includes the private headers, so no
|
||||
extra package is required there. KDE Frameworks are not practically
|
||||
available via Homebrew, so macOS builds are normally done **without KF**
|
||||
(`-DBUILD_WITH_KF=OFF`) — see the caveat below.
|
||||
|
||||
Apple's Clang (from the Xcode Command Line Tools, `xcode-select --install`)
|
||||
is the default and needs no extra package; GCC is available via
|
||||
`brew install gcc` if you specifically want it instead.
|
||||
|
||||
Optional, for a system pugixml: `brew install pugixml`.
|
||||
|
||||
### Windows
|
||||
|
||||
See [Building on Windows](#6-building-on-windows-msvc--mingw) below — the
|
||||
package sources differ enough from the Unix-like platforms above (no system
|
||||
package manager, SQLite3 and Qt aren't provided the same way) that it gets
|
||||
its own section.
|
||||
|
||||
## 5. pugixml
|
||||
|
||||
QET links against [pugixml](https://pugixml.org) for XML parsing.
|
||||
`cmake/fetch_pugixml.cmake` handles this automatically: if a suitable
|
||||
pugixml isn't already available on the system, CMake fetches and builds it
|
||||
from source via `FetchContent` as part of the normal configure step — you
|
||||
don't need to do anything to get a working build.
|
||||
|
||||
If you'd rather avoid that network fetch and use your distribution's own
|
||||
pugixml package instead, install it before running `cmake ..` (package
|
||||
names are listed per platform in the [Distribution
|
||||
packages](#4-distribution-packages) section above — e.g. `libpugixml-dev`
|
||||
on Debian/Ubuntu, `pugixml-devel` on Fedora).
|
||||
|
||||
## 6. Building on Windows (MSVC / MinGW)
|
||||
|
||||
Both toolchains QET's CMake build targets on Windows are covered here:
|
||||
**MSVC** (Visual Studio 2019/2022) and **MinGW-w64** (gcc). Unlike the
|
||||
Unix-like platforms above, there's no single system package manager, so
|
||||
Qt, SQLite3 and (optionally) KDE Frameworks each need to be sourced
|
||||
separately per toolchain.
|
||||
|
||||
One piece of good news either way: unlike Debian/Fedora, the official Qt
|
||||
Windows kits (both MSVC and MinGW) **already include the GuiPrivate private
|
||||
headers** — there's no separate "private headers" package to remember on
|
||||
Windows (see [Qt6 private headers](#7-qt6-private-headers-mandatory) below
|
||||
for why this matters).
|
||||
|
||||
`QtPdf` is available as an optional component in the Qt Online Installer
|
||||
(look for "Qt PDF" under the Qt 6.4+ node); if you skip it, PDF page import
|
||||
is silently disabled exactly as on the other platforms. KDE Frameworks are
|
||||
not prebuilt for Windows by any of the routes below, so Windows builds
|
||||
normally use `-DBUILD_WITH_KF=OFF` (see the
|
||||
[autosave caveat](#9-building-without-kde-frameworks)).
|
||||
|
||||
### MSVC (Visual Studio 2019 / 2022)
|
||||
|
||||
1. Install Visual Studio with the "Desktop development with C++" workload,
|
||||
and install Qt6 for MSVC (e.g. the `msvc2019_64` or `msvc2022_64` kit)
|
||||
via the [Qt Online Installer](https://www.qt.io/download-qt-installer).
|
||||
2. Get SQLite3 — the simplest route is [vcpkg](https://vcpkg.io):
|
||||
```bat
|
||||
vcpkg install sqlite3:x64-windows
|
||||
```
|
||||
3. Configure and build from an "x64 Native Tools Command Prompt for VS":
|
||||
```bat
|
||||
mkdir build && cd build
|
||||
cmake .. -G "Visual Studio 17 2022" -A x64 ^
|
||||
-DCMAKE_PREFIX_PATH="C:\Qt\6.x.x\msvc2022_64" ^
|
||||
-DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" ^
|
||||
-DBUILD_WITH_KF=OFF
|
||||
cmake --build . --config Release --parallel
|
||||
```
|
||||
Ninja works too, in place of the Visual Studio generator, if you prefer
|
||||
(`-G Ninja -DCMAKE_BUILD_TYPE=Release`, run from the same VS developer
|
||||
prompt so `cl.exe` is on `PATH`).
|
||||
|
||||
### MinGW-w64 (gcc)
|
||||
|
||||
Two common ways to get a MinGW toolchain that matches a Qt6 MinGW kit: Qt's
|
||||
own bundled MinGW (installed alongside a `mingw_64` Qt kit via the Qt
|
||||
Online Installer), or [MSYS2](https://www.msys2.org).
|
||||
|
||||
Using MSYS2, from a **MINGW64** shell:
|
||||
```sh
|
||||
pacman -S --needed \
|
||||
mingw-w64-x86_64-toolchain \
|
||||
mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-tools \
|
||||
mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja \
|
||||
mingw-w64-x86_64-sqlite3
|
||||
|
||||
mkdir build && cd build
|
||||
cmake .. -G Ninja -DBUILD_WITH_KF=OFF -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build .
|
||||
```
|
||||
(KF6 isn't packaged in MSYS2 either, hence `-DBUILD_WITH_KF=OFF` again.)
|
||||
|
||||
Using the Qt Online Installer's bundled MinGW kit instead: point
|
||||
`CMAKE_PREFIX_PATH` at that kit (e.g. `C:\Qt\6.x.x\mingw_64`) and make sure
|
||||
its bundled `g++.exe` comes first on `PATH`, or pass
|
||||
`-DCMAKE_C_COMPILER`/`-DCMAKE_CXX_COMPILER` explicitly so CMake doesn't pick
|
||||
up a different MinGW installation. SQLite3 still has to come from elsewhere
|
||||
in this path — vcpkg with a `mingw`-flavoured triplet, or MSYS2's package as
|
||||
above.
|
||||
|
||||
## 7. Qt6 private headers (mandatory)
|
||||
|
||||
QET uses the private `QPdfEngine` API (`<private/qpdf_p.h>`) to produce
|
||||
clickable hyperlinks in PDF export. This requires Qt's `GuiPrivate` target,
|
||||
which on several distributions (notably Debian/Ubuntu) is shipped in a
|
||||
separate "private headers" package rather than the normal `-dev` package —
|
||||
e.g. `qt6-base-private-dev` on Debian/Ubuntu, or
|
||||
`qt6-qtbase-private-devel` on Fedora. Without it, CMake's `find_package`
|
||||
step succeeds but configuration later fails at generate time with:
|
||||
|
||||
```
|
||||
Imported target "Qt6::GuiPrivate" includes non-existent path
|
||||
```
|
||||
|
||||
If you hit this, install your distribution's Qt6 private-headers package
|
||||
(on Windows this is a non-issue — see [Building on
|
||||
Windows](#6-building-on-windows-msvc--mingw) above).
|
||||
|
||||
## 8. PDF page import (QtPdf)
|
||||
|
||||
The toolbar's "Add a PDF" feature (`QPdfDocument::pagePointSize()`) needs
|
||||
the separate `QtPdf` Qt module, available since Qt 6.4.
|
||||
|
||||
**This is optional and soft-fails**: if `QtPdf` isn't found, or is present
|
||||
but older than 6.4, CMake prints a status message and simply disables the
|
||||
feature (`QET_HAS_QTPDF` stays `FALSE`) — it does **not** stop the build.
|
||||
Some Qt6 distributions don't ship `QtPdf` at all (it lives outside Qt's
|
||||
core module set, alongside QtWebEngine), so this is expected on several
|
||||
platforms, including FreeBSD as of this writing.
|
||||
|
||||
## 9. Building without KDE Frameworks
|
||||
|
||||
`BUILD_WITH_KF=OFF` builds QET against a bundled fallback UI layer instead
|
||||
of KDE Frameworks (`kcoreaddons`/`kwidgetsaddons`). This is a fully
|
||||
supported configuration and is, in practice, the default on platforms where
|
||||
KF6 isn't readily packaged (macOS and Windows in particular).
|
||||
|
||||
Almost everything works identically either way. The one known caveat:
|
||||
**autosave behavior is not as polished without KF**, since QET relies on
|
||||
KCoreAddons' autosave/backup-file handling when it's available. Expect
|
||||
autosave to work, but less robustly than on a KF-enabled build.
|
||||
|
||||
## 10. Translations (developer operation)
|
||||
|
||||
Everything in this section is a **maintainer/translator task**, not
|
||||
something a normal build or a packager needs to touch.
|
||||
|
||||
The `.qm` files shipped with the application are compiled from the tracked
|
||||
`.ts` files automatically as part of every normal build (via `lrelease`) —
|
||||
regular builds and packages get up-to-date translated UI strings for free,
|
||||
with no developer action needed.
|
||||
|
||||
Refreshing the `.ts` files themselves from the source code (`lupdate`) is
|
||||
the actual developer operation: it's exposed as its own opt-in build
|
||||
target, separate from the normal build:
|
||||
|
||||
```sh
|
||||
cmake --build . --target update_translations
|
||||
```
|
||||
|
||||
This is **not** run automatically and should not be added to routine or
|
||||
parallel CI builds: it rewrites the tracked `.ts` files as a side effect,
|
||||
and running it concurrently with the normal `lrelease` compilation step (as
|
||||
would happen under `-j`/parallel builds) can corrupt a `.ts` file mid-write,
|
||||
causing `lrelease` to fail with "Premature end of document". Run it on its
|
||||
own, review the diff, and commit the updated `.ts` files separately.
|
||||
@@ -1,60 +1,60 @@
|
||||
[ca]
|
||||
QElectroTech és una aplicació Qt5 per crear esquemes elèctrics.
|
||||
QElectroTech és una aplicació Qt6 per crear esquemes elèctrics.
|
||||
QET utilitza el format XML per als seus elements i esquemes i inclou un editor d'esquemes, un editor d'elements i un editor de caixetins.
|
||||
|
||||
[en]
|
||||
QElectroTech is a Qt5 application to design electric diagrams.
|
||||
QElectroTech is a Qt6 application to design electric diagrams.
|
||||
It uses XML files for elements and diagrams, and includes both a diagram editor, a element editor, and an titleblock editor.
|
||||
|
||||
[fr]
|
||||
QElectroTech est une application Qt5 pour réaliser des schémas électriques.
|
||||
QElectroTech est une application Qt6 pour réaliser des schémas électriques.
|
||||
QET utilise le format XML pour ses éléments et ses schémas et inclut un éditeur de schémas, un éditeur d'élément, ainsi qu'un editeur de cartouche.
|
||||
|
||||
[de]
|
||||
QElectroTech ist eine Qt5 Software, um Schaltpläne zu erstellen.
|
||||
QElectroTech ist eine Qt6 Software, um Schaltpläne zu erstellen.
|
||||
QET benutzt das XML Format für seine Bauteile und seine Projekte, und beinhaltet einen Schaltplaneditor, einen Bauteileditor sowie einen Schriftfeldeditor.
|
||||
|
||||
|
||||
[ru]
|
||||
QElectroTech - приложение написанное на Qt5 и предназначенное для разработки электрических схем.
|
||||
QElectroTech - приложение написанное на Qt6 и предназначенное для разработки электрических схем.
|
||||
Оно использует XML-файлы для элементов и схем, и включает, как редактор схем, так и редактор элементов.
|
||||
|
||||
[pt]
|
||||
QElectroTech é uma aplicação baseada em Qt5 para desenhar esquemas eléctricos.
|
||||
QElectroTech é uma aplicação baseada em Qt6 para desenhar esquemas eléctricos.
|
||||
QET utiliza ficheiros XML para os elementos e para os esquemas e inclui um editor de esquemas e um editor de elementos.
|
||||
|
||||
[es]
|
||||
QElectroTech es una aplicación Qt5 para diseñar esquemas eléctricos.
|
||||
QElectroTech es una aplicación Qt6 para diseñar esquemas eléctricos.
|
||||
Utiliza archivos XML para los elementos y esquemas, e incluye un editor de esquemas y un editor de elementos.
|
||||
|
||||
[cs]
|
||||
QElectroTech je aplikací Qt5 určenou pro návrh nákresů elektrických obvodů.
|
||||
QElectroTech je aplikací Qt6 určenou pro návrh nákresů elektrických obvodů.
|
||||
Pro prvky a nákresy používá soubory XML, a zahrnuje v sobě jak editor nákresů, tak editor prvků.
|
||||
|
||||
[pl]
|
||||
QElectroTech to aplikacja napisana w Qt5, przeznaczona do tworzenia schematów elektrycznych.
|
||||
QElectroTech to aplikacja napisana w Qt6, przeznaczona do tworzenia schematów elektrycznych.
|
||||
Wykorzystuje XML do zapisywania plików elementów i projektów. Posiada edytor schematów i elementów.
|
||||
|
||||
[it]
|
||||
QElectroTech è una applicazione fatta in Qt5 per disegnare schemi elettrici.
|
||||
QElectroTech è una applicazione fatta in Qt6 per disegnare schemi elettrici.
|
||||
QET usa il formato XML per i suoi elementi e schemi, includendo anche un editor per gli stessi.
|
||||
|
||||
[el]
|
||||
Το QElectroTech είναι μια εφαρμογή Qt5 για σχεδίαση ηλεκτρικών διαγραμμάτων.
|
||||
Το QElectroTech είναι μια εφαρμογή Qt6 για σχεδίαση ηλεκτρικών διαγραμμάτων.
|
||||
Χρησιμοποιεί αρχεία XML για στοιχεία και διαγράμματα, και περιλαμβάνει επεξεργαστή διαγραμμάτων καθώς και επεξεργαστή στοιχείων.
|
||||
|
||||
[nl]
|
||||
QElectroTech is een Qt5 applicatie om elektrische schema's te ontwerpen.
|
||||
QElectroTech is een Qt6 applicatie om elektrische schema's te ontwerpen.
|
||||
Het maakt gebruik van XML-bestanden voor elementen en diagrammen, en omvat zowel een diagram bewerker, een element bewerker, en een bloksjabloon bewerker.
|
||||
|
||||
[be]
|
||||
QElectroTech is een Qt5 toepassing voor het maken en beheren van elektrische schema's.
|
||||
QElectroTech is een Qt6 toepassing voor het maken en beheren van elektrische schema's.
|
||||
QET gebruikt XML voor de elementen en schema's en omvat een schematische editor, itemeditor, en een titel sjabloon editor.
|
||||
|
||||
[da]
|
||||
QElectroTech er et Qt5 program til at redigere elektriske diagrammer.
|
||||
QElectroTech er et Qt6 program til at redigere elektriske diagrammer.
|
||||
Det bruger XML filer for symboler og diagrammer og inkluderer diagram, symbol og titelblok redigering.
|
||||
|
||||
[ja]
|
||||
QElectroTech は電気回路図を作成する Qt5 アプリケーションです。
|
||||
QElectroTech は電気回路図を作成する Qt6 アプリケーションです。
|
||||
QET は要素と回路図に XML 形式を利用し、回路図エディタ、要素エディタ、表題欄エディタを含みます。
|
||||
|
||||
@@ -40,16 +40,16 @@ git clone --recursive https://github.com/qelectrotech/qelectrotech-source-mirror
|
||||
Here are the technical choices made for the software development:
|
||||
|
||||
* Integrated development environment: [Qt Framework](https://www.qt.io/ide/)
|
||||
* Libraries: Qt 5.x
|
||||
* [KF5 Framework](https://github.com/KDE)
|
||||
* Libraries: Qt 6.x
|
||||
* [KF6 Framework](https://github.com/KDE)
|
||||
[Cmake](https://cmake.org/install/)
|
||||
[kcoreaddons](https://github.com/KDE/kcoreaddons/tree/kf5)
|
||||
[kwidgetsaddons](https://github.com/KDE/kwidgetsaddons/tree/kf5).
|
||||
[kcoreaddons](https://github.com/KDE/kcoreaddons/tree/kf6)
|
||||
[kwidgetsaddons](https://github.com/KDE/kwidgetsaddons/tree/kf6).
|
||||
* Coding language: [C++](https://en.wikipedia.org/wiki/C%2B%2B)
|
||||
* GUI translations: [Qt Linguist](http://doc.qt.io/qt-5/qtlinguist-index.html)
|
||||
* GUI translations: [Qt Linguist](http://doc.qt.io/qt-6/qtlinguist-index.html)
|
||||
* Version control: [GIT](https://github.com/qelectrotech/qelectrotech-source-mirror.git)
|
||||
* Doxygen documentation :[Doxygen](https://qelectrotech.github.io/qelectrotech-source-mirror/)
|
||||
* QtCreator qch doxygen :[QElectroTech.qch](https://github.com/qelectrotech/qelectrotech-source-mirror/blob/master/doc/QElectroTech.qch)
|
||||
* Doxygen documentation :[Doxygen](https://download.qelectrotech.org/qet/doxygen/html/)
|
||||
* QtCreator qch doxygen :[QElectroTech.qch](https://download.qelectrotech.org/qet/doxygen/QElectroTech.qch)
|
||||
* File format for projects, elements and titleblocks: [XML](http://www.w3schools.com/xml/xml_whatis.asp)
|
||||
* Main development platform: [GNU/Linux](http://getgnulinux.org/en/linux/)
|
||||
* Targeted platforms: Windows, GNU/Linux, Mac OS X, BSDs
|
||||
|
||||
@@ -73,6 +73,7 @@ parts:
|
||||
- git
|
||||
- sqlite3
|
||||
- xdg-user-dirs
|
||||
- libqt6qml6
|
||||
# libxcb-cursor0 workaround was needed against the Qt5/KF5 core22 content
|
||||
# snap (issue #373). Not yet re-verified against kf6-core24 — remove this
|
||||
# if the Qt6 xcb platform plugin loads cleanly without it.
|
||||
@@ -84,7 +85,13 @@ parts:
|
||||
- libsqlite3-dev
|
||||
- qt6-tools-dev
|
||||
- qt6-base-private-dev
|
||||
- qt6-declarative-dev
|
||||
- pkgconf
|
||||
# Qt6 PrintSupport records Cups::Cups as a third-party dependency
|
||||
# (qprint_p.h includes <cups/ppd.h>), so find_package(Qt6 PrintSupport)
|
||||
# runs FindCups at configure time and fails without the CUPS headers.
|
||||
# Build-time only: nothing from it is staged into the snap.
|
||||
- libcups2-dev
|
||||
override-build: |
|
||||
displayed_version=$(cat sources/qetversion.cpp | grep "return QVersionNumber{"| head -n 1| awk -F "{" '{ print $2 }' | awk -F "}" '{ print $1 }' | sed -e 's/,/./g' -e 's/ //g')
|
||||
snap_version="${displayed_version}-g$(git rev-parse --short=8 HEAD)"
|
||||
|
||||
@@ -68,4 +68,3 @@ else()
|
||||
add_definitions(-DBUILD_WITHOUT_KF)
|
||||
endif()
|
||||
message("QET_COMPONENTS :" ${QET_COMPONENTS})
|
||||
message("QT_VERSION_MAJOR :" ${QT_VERSION_MAJOR})
|
||||
|
||||
@@ -31,10 +31,7 @@ add_definitions(-DQT_MESSAGELOGCONTEXT)
|
||||
# In order to do so, uncomment the following line.
|
||||
#add_definitions(-DTODO_LIST)
|
||||
|
||||
# Build with KDE Frameworks. The major version (KF5/KF6) is derived
|
||||
# automatically from QT_VERSION_MAJOR -- KDE Frameworks deliberately
|
||||
# mirrors Qt's own major version numbering, so there is no independent
|
||||
# choice to make here. See cmake/fetch_kdeaddons.cmake.
|
||||
# Build with KDE Frameworks.
|
||||
option(BUILD_WITH_KF "Build with KDE Frameworks" ON)
|
||||
|
||||
# Precompiled headers for the Qt umbrella headers.
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
message(" - fetch_kdeaddons")
|
||||
|
||||
# TODO remove path as soon as Qt5 gets retired
|
||||
if(BUILD_WITH_KF)
|
||||
Include(FetchContent)
|
||||
|
||||
@@ -24,16 +23,9 @@ if(BUILD_WITH_KF)
|
||||
|
||||
if(BUILD_KF)
|
||||
|
||||
if(KF_MAJOR_VERSION EQUAL 5)
|
||||
if(NOT DEFINED KF_GIT_TAG)
|
||||
#https://qelectrotech.org/forum/viewtopic.php?pid=13924#p13924
|
||||
set(KF_GIT_TAG v5.77.0)
|
||||
endif()
|
||||
else()
|
||||
if(NOT DEFINED KF_GIT_TAG)
|
||||
# this is a more or less random version, taken as an conservative approach
|
||||
set(KF_GIT_TAG v6.10.0)
|
||||
endif()
|
||||
if(NOT DEFINED KF_GIT_TAG)
|
||||
# this is a more or less random version, taken as an conservative approach
|
||||
set(KF_GIT_TAG v6.10.0)
|
||||
endif()
|
||||
# using a function in order to limit the scope of the variables
|
||||
# with CMake >=3.25 we could use a block()
|
||||
@@ -78,12 +70,12 @@ if(BUILD_WITH_KF)
|
||||
endfunction()
|
||||
qet_make_kf_available()
|
||||
else()
|
||||
find_package(KF${KF_MAJOR_VERSION}CoreAddons REQUIRED)
|
||||
find_package(KF${KF_MAJOR_VERSION}WidgetsAddons REQUIRED)
|
||||
find_package(KF6CoreAddons REQUIRED)
|
||||
find_package(KF6WidgetsAddons REQUIRED)
|
||||
endif()
|
||||
|
||||
set(KF_PRIVATE_LIBRARIES
|
||||
KF${KF_MAJOR_VERSION}::WidgetsAddons
|
||||
KF${KF_MAJOR_VERSION}::CoreAddons
|
||||
KF6::WidgetsAddons
|
||||
KF6::CoreAddons
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -26,7 +26,7 @@ if(BUILD_PUGIXML)
|
||||
pugixml
|
||||
GIT_REPOSITORY https://github.com/zeux/pugixml.git
|
||||
GIT_TAG v1.15)
|
||||
|
||||
set(PUGIXML_INSTALL OFF CACHE INTERNAL "")
|
||||
FetchContent_MakeAvailable(pugixml)
|
||||
else()
|
||||
find_package(pugixml REQUIRED)
|
||||
|
||||
@@ -35,5 +35,5 @@ FetchContent_Declare(
|
||||
SingleApplication
|
||||
GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git
|
||||
GIT_TAG v3.2.0)
|
||||
|
||||
set(QT_DEFAULT_MAJOR_VERSION 6)
|
||||
FetchContent_MakeAvailable(SingleApplication)
|
||||
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
message(" - qet_compilation_vars")
|
||||
|
||||
# Note: GuiPrivate is intentionally NOT in this list. Qt6's CMake config only
|
||||
# creates the Qt::GuiPrivate target when "GuiPrivate" is explicitly requested
|
||||
# as a component, but Qt5 has no Qt5GuiPrivate package at all (the target is
|
||||
# created implicitly with Gui), so requesting it as a component breaks the
|
||||
# whole Qt5 configure. It is requested separately, guarded by
|
||||
# QT_VERSION_MAJOR, after the main find_package.
|
||||
# Note: GuiPrivate is intentionally NOT in this list.
|
||||
# Qt >= 6.7 ships it as a proper find_package component, but some distro
|
||||
# packages (e.g. Ubuntu's qt6-base-private-dev) omit Qt6GuiPrivateConfig.cmake
|
||||
# and only provide the implicit Qt6::GuiPrivate target created alongside
|
||||
# Qt6::Gui. Checks are done in the main CMakeLists.txt
|
||||
# (Needed for QPdfEngine::drawHyperlink, the PDF internal links.)
|
||||
set(QET_COMPONENTS
|
||||
LinguistTools
|
||||
@@ -174,7 +173,11 @@ set(QET_SRC_FILES
|
||||
${QET_DIR}/sources/conductornumexport.cpp
|
||||
${QET_DIR}/sources/wiringlistexport.h
|
||||
${QET_DIR}/sources/wiringlistexport.cpp
|
||||
${QET_DIR}/sources/ui/wiringlistdialog.h
|
||||
${QET_DIR}/sources/ui/wiringlistdialog.cpp
|
||||
${QET_DIR}/sources/conductornumexport.h
|
||||
${QET_DIR}/sources/bomexport.cpp
|
||||
${QET_DIR}/sources/bomexport.h
|
||||
${QET_DIR}/sources/conductorprofile.cpp
|
||||
${QET_DIR}/sources/conductorprofile.h
|
||||
${QET_DIR}/sources/conductorproperties.cpp
|
||||
@@ -245,6 +248,8 @@ set(QET_SRC_FILES
|
||||
${QET_DIR}/sources/qet.h
|
||||
${QET_DIR}/sources/qeticons.cpp
|
||||
${QET_DIR}/sources/qeticons.h
|
||||
${QET_DIR}/sources/qetpalette.cpp
|
||||
${QET_DIR}/sources/qetpalette.h
|
||||
${QET_DIR}/sources/qetinformation.cpp
|
||||
${QET_DIR}/sources/qetinformation.h
|
||||
${QET_DIR}/sources/qetmainwindow.cpp
|
||||
@@ -326,6 +331,8 @@ set(QET_SRC_FILES
|
||||
${QET_DIR}/sources/diagramevent/diagrameventinterface.h
|
||||
${QET_DIR}/sources/diagramevent/diagrameventaddmacro.cpp
|
||||
${QET_DIR}/sources/diagramevent/diagrameventaddmacro.h
|
||||
${QET_DIR}/sources/diagramevent/diagrameventaddpaste.cpp
|
||||
${QET_DIR}/sources/diagramevent/diagrameventaddpaste.h
|
||||
|
||||
${QET_DIR}/sources/dvevent/dveventinterface.cpp
|
||||
${QET_DIR}/sources/dvevent/dveventinterface.h
|
||||
@@ -473,6 +480,8 @@ set(QET_SRC_FILES
|
||||
${QET_DIR}/sources/project/projectusagetracker.cpp
|
||||
${QET_DIR}/sources/project/projectusagetracker.h
|
||||
|
||||
${QET_DIR}/sources/properties/deviceinformation.cpp
|
||||
${QET_DIR}/sources/properties/deviceinformation.h
|
||||
${QET_DIR}/sources/properties/elementdata.cpp
|
||||
${QET_DIR}/sources/properties/elementdata.h
|
||||
${QET_DIR}/sources/properties/propertiesinterface.cpp
|
||||
@@ -831,15 +840,26 @@ if(NOT BUILD_WITH_KF)
|
||||
)
|
||||
endif()
|
||||
|
||||
# Qt6-only: PDF page import files
|
||||
if(QT_VERSION_MAJOR GREATER_EQUAL 6)
|
||||
list(APPEND QET_SRC_FILES
|
||||
list(APPEND QET_SRC_FILES
|
||||
${QET_DIR}/sources/diagramevent/diagrameventaddpdf.cpp
|
||||
${QET_DIR}/sources/diagramevent/diagrameventaddpdf.h
|
||||
${QET_DIR}/sources/ui/pdfpagesdialog.cpp
|
||||
${QET_DIR}/sources/ui/pdfpagesdialog.h
|
||||
)
|
||||
endif()
|
||||
)
|
||||
|
||||
# JavaScript scripting (bugtracker #162). Unconditionally in the source
|
||||
# list, like the QtPdf files above: this file is included before the
|
||||
# QET_HAS_SCRIPTING probe runs in the top-level CMakeLists.txt, so the
|
||||
# variable isn't set yet here. Same pattern as QtPdf: always compiled, the
|
||||
# actual Qt::Qml dependent code is behind #ifdef QET_HAS_SCRIPTING inside
|
||||
# qetscripting.cpp/qetscriptapi.cpp themselves, compiling to a harmless
|
||||
# stub when the module wasn't found.
|
||||
list(APPEND QET_SRC_FILES
|
||||
${QET_DIR}/sources/scripting/qetscriptapi.cpp
|
||||
${QET_DIR}/sources/scripting/qetscriptapi.h
|
||||
${QET_DIR}/sources/scripting/qetscripting.cpp
|
||||
${QET_DIR}/sources/scripting/qetscripting.h
|
||||
)
|
||||
|
||||
set(TS_FILES
|
||||
${QET_DIR}/lang/qet_ar.ts
|
||||
@@ -856,6 +876,7 @@ set(TS_FILES
|
||||
${QET_DIR}/lang/qet_hu.ts
|
||||
${QET_DIR}/lang/qet_it.ts
|
||||
${QET_DIR}/lang/qet_ja.ts
|
||||
${QET_DIR}/lang/qet_ko.ts
|
||||
${QET_DIR}/lang/qet_mn.ts
|
||||
${QET_DIR}/lang/qet_nb.ts
|
||||
${QET_DIR}/lang/qet_nl.ts
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# Smart Device Information and BOM CSV
|
||||
|
||||
## Architecture
|
||||
|
||||
- A `.qet` project is XML. Placed component properties are held in
|
||||
`ElementData::m_informations`, a `DiagramContext`, and are serialized by the
|
||||
existing `Element::fromXml()` and `Element::toXml()` path.
|
||||
- `DeviceInformation` is a typed view over that existing context. It does not
|
||||
introduce a second data store. Updates made by the properties editor continue
|
||||
to use `ChangeElementInformationCommand`, including undo/redo and dirty state.
|
||||
- The project database copies element contexts into `element_info` and exposes
|
||||
reporting fields through `element_nomenclature_view`.
|
||||
- GUI and CLI BOM exports both use `BomExport::defaultQuery()` against that
|
||||
view. The existing `BOMExportDialog` remains the only GUI export entry point;
|
||||
users can still customize columns, filters, and grouped/ungrouped output.
|
||||
|
||||
## Device Properties
|
||||
|
||||
| Device field | XML/context key | Default BOM |
|
||||
| --- | --- | --- |
|
||||
| Device tag | `label` | Yes |
|
||||
| Manufacturer | `manufacturer` | Yes |
|
||||
| Part number | `manufacturer_reference` | Yes |
|
||||
| Model | `model` | Yes |
|
||||
| Description | `description` | Yes |
|
||||
| Category | `category` | Yes |
|
||||
| Quantity | `quantity` | Yes |
|
||||
| Voltage rating | `voltage_rating` | Yes |
|
||||
| Current rating | `current_rating` | Yes |
|
||||
| Page | `folio` from the diagram | Yes |
|
||||
| Notes | `notes` | Yes |
|
||||
|
||||
The five new context keys are `model`, `category`, `voltage_rating`,
|
||||
`current_rating`, and `notes`. They are available in the existing information
|
||||
editor for Simple and Master elements, in symbol definitions, in the SQL
|
||||
nomenclature view, and in the export column picker.
|
||||
|
||||
No XML version bump or migration is required. Missing keys read as empty
|
||||
strings, empty properties are omitted by the existing writer, and unknown
|
||||
context keys remain preserved. Quantity and ratings stay free text so existing
|
||||
unit conventions and decimal quantities are not changed implicitly.
|
||||
|
||||
## BOM Policy
|
||||
|
||||
The default BOM query exports one row per Simple or Master element. Slave
|
||||
contacts, terminal-strip elements, reports, thumbnails, and conductor
|
||||
definitions are excluded. A Master device is counted once and PLC I/O entries
|
||||
are not expanded. The existing `exclude_from_bom` property is honored by the
|
||||
SQL view, including common true representations (`true`, `1`, `yes`, `on`).
|
||||
|
||||
The default columns are:
|
||||
|
||||
`Device tag, Designation, Manufacturer, Part number, Model, Description,
|
||||
Category, Quantity, Voltage rating, Current rating, Page, Notes`.
|
||||
|
||||
The existing **Format as bill of materials** checkbox provides grouped output;
|
||||
it is off by default so the initial export remains ungrouped. Users may change
|
||||
the query and column order through the existing dialog. The command-line
|
||||
`--export-bom` operation uses the same default query and column order.
|
||||
|
||||
CSV output is UTF-8 with a BOM, semicolon-delimited, and quotes every field.
|
||||
Embedded quotes are doubled and embedded newlines are retained. `QSaveFile`
|
||||
provides atomic replacement; query, open, write, and commit failures are
|
||||
reported without deleting an existing destination first.
|
||||
|
||||
## Verification
|
||||
|
||||
The smart-device test is registered explicitly in
|
||||
`tests/qttest/CMakeLists.txt` and uses only Qt Test and Qt SQL. It is therefore
|
||||
part of the normal cross-platform CMake/CTest flow:
|
||||
|
||||
```sh
|
||||
cmake -S . -B build -DPACKAGE_TESTS=ON
|
||||
cmake --build build
|
||||
ctest --test-dir build --output-on-failure
|
||||
```
|
||||
|
||||
`tst_smart_device` checks the metadata column contract, Simple/Master filtering,
|
||||
stable page ordering, UTF-8 with Latin and non-Latin samples, CSV escaping, and
|
||||
atomic write success/failure. Existing project XML save/load tests cover the
|
||||
generic `DiagramContext` persistence path used by the new keys.
|
||||
|
||||
Manual checks:
|
||||
|
||||
1. Open an existing project and edit a Simple or Master element's information.
|
||||
2. Set all device fields, apply, undo, redo, save, close, and reopen.
|
||||
3. Open Project > Export as CSV and verify the device columns are preselected.
|
||||
4. Export with grouping both disabled and enabled.
|
||||
5. Verify leading-zero part numbers, non-Latin text, quotes, and newlines in a
|
||||
UTF-8 CSV reader.
|
||||
|
||||
Cable management, terminal-strip planning, automatic wire numbering, PLC I/O
|
||||
expansion, panel layout, and manufacturer catalog integration are out of scope.
|
||||
+1
-1
Submodule elements updated: 74bdb77844...60eacc28a6
File diff suppressed because one or more lines are too long
Binary file not shown.
+1120
-836
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+574
-543
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1095
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1092
-817
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1093
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1092
-817
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1099
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1116
-839
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+4891
-1856
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1389
-1112
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1109
-830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1090
-817
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1093
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1089
-816
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1088
-813
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1092
-815
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1116
-839
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+4544
-1620
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1093
-818
File diff suppressed because it is too large
Load Diff
+1127
-850
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+4904
-1869
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+574
-511
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1107
-830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1093
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1115
-838
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1129
-850
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1095
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1117
-838
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1119
-838
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1117
-838
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1092
-817
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1090
-817
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1095
-818
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1090
-817
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1
-1
@@ -42,7 +42,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>qelectrotech</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.qelectrotech</string>
|
||||
<string>org.qelectrotech.QElectroTech</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -1,337 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2019 The QElectroTech Team
|
||||
# This file is part of QElectroTech.
|
||||
|
||||
# QElectroTech is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# QElectroTech 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 General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
# Need homebrew and coreutils installed see <http://brew.sh>.
|
||||
|
||||
|
||||
#Force MacOSX12.3.sdk
|
||||
#see: https://www.downtowndougbrown.com/2023/08/how-to-create-a-qt-5-arm-intel-universal-binary-for-mac/
|
||||
|
||||
export DEVELOPER_DIR=/Applications/Xcode_14.01.app/Contents/Developer
|
||||
|
||||
# configuration
|
||||
APPNAME='qelectrotech'
|
||||
BUNDLE=$APPNAME.app
|
||||
APPBIN="$BUNDLE/Contents/MacOS/$APPNAME"
|
||||
|
||||
# Emplacement du script
|
||||
current_dir=$(dirname "$0")
|
||||
|
||||
# On se remet au depart
|
||||
cd "${current_dir}/../"
|
||||
|
||||
# Emplacement courant
|
||||
current_dir=$(PWD)
|
||||
|
||||
|
||||
### get system configuration ########################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "This script prepares a Qt application bundle for deployment."
|
||||
echo "Please see the \"Deploying an Application on Qt/Mac\""
|
||||
echo "page in the Qt documentation for more information."
|
||||
echo
|
||||
echo "This script :"
|
||||
echo "\t - up date the svn depot"
|
||||
echo "\t - built the application bundle,"
|
||||
echo "\t - copy over required Qt frameworks,"
|
||||
echo "\t - copy additional files: translations, titleblocks and elements,"
|
||||
echo "\t - create image disk."
|
||||
echo
|
||||
echo "Enjoy ;-)"
|
||||
echo
|
||||
|
||||
# as long as we can find qmake, we don't need QTDIR
|
||||
FWPATH=`qmake -query QT_INSTALL_LIBS`
|
||||
if [ ! -d $FWPATH/QtGui.framework ] ; then
|
||||
echo "ERROR: cannot find the Qt frameworks. Make sure Qt is installed"
|
||||
echo "and qmake is in your environment path."
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
### GIT ####################################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Run GIT:"
|
||||
|
||||
# recupere le numero de la dernière revision
|
||||
# Si il y a ':' garde la 2e partie
|
||||
# Remplace les lettres par 'rien'
|
||||
#revAv=$(svnversion | cut -d : -f 2 | tr -d '[:alpha:]')
|
||||
|
||||
# Fait une mise à jour
|
||||
git submodule init
|
||||
git submodule update
|
||||
git pull --recurse-submodules
|
||||
git pull
|
||||
#git checkout foliolist_position
|
||||
|
||||
# recupere le numero de la nouvelle revision
|
||||
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
A=$(git rev-list HEAD --count)
|
||||
HEAD=$(($A+473))
|
||||
|
||||
|
||||
VERSION=$(cat sources/qetversion.cpp | grep "return QVersionNumber{"| head -n 1| awk -F "{" '{ print $2 }' | awk -F "}" '{ print $1 }' | sed -e 's/,/./g' -e 's/ //g')
|
||||
#VERSION=$(cat sources/qetversion.cpp | grep "return QVersionNumber{ 0, "| head -n 1| cut -c25-35| sed -e 's/,/./g' -e 's/ //g') #Find major, minor, and micro version numbers in sources/qetversion.cp
|
||||
|
||||
# Dmg de la dernière revision déjà créé
|
||||
if [ -e "build-aux/mac-osx/${APPNAME} $VERSION r$HEAD.dmg" ] ; then
|
||||
echo "There are not new updates, make disk image can"
|
||||
echo "take a lot of time (5 min). Can you continu?"
|
||||
echo "[y/n]"
|
||||
read userinput
|
||||
if [ "$userinput" == "n" ] ; then
|
||||
echo
|
||||
echo "Process is stopped."
|
||||
echo
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
### make install ####################################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Run make install:"
|
||||
|
||||
# pour effacer l’ancienne compilation
|
||||
if [ -d $BUNDLE ] ; then
|
||||
echo "Removing hold bundle..."
|
||||
rm -rf $BUNDLE
|
||||
fi
|
||||
if [ -e Makefile ] ; then
|
||||
echo "Removing hold Makefile..."
|
||||
make clean
|
||||
fi
|
||||
|
||||
# genere le Makefile
|
||||
echo "Generating new makefile..."
|
||||
qmake -spec macx-clang
|
||||
|
||||
# compilation
|
||||
if [ -e Makefile.Release ] ; then
|
||||
START_TIME=$SECONDS
|
||||
|
||||
# arret du script si erreur de compilation
|
||||
testSuccessBuild () {
|
||||
if [ $? -ne 0 ]; then
|
||||
cleanVerionTag
|
||||
ELAPSED_TIME=$(($SECONDS - $START_TIME))
|
||||
echo
|
||||
echo "make failed - $(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# utilise tout les coeurs pour une compilation plus rapide
|
||||
coeur=$(sysctl hw.ncpu | awk '{print $2}')
|
||||
if [ $? -ne 0 ]; then
|
||||
make -f Makefile.Release
|
||||
testSuccessBuild
|
||||
else
|
||||
make -j$(($coeur + 1)) -f Makefile.Release
|
||||
testSuccessBuild
|
||||
fi
|
||||
|
||||
cleanVerionTag
|
||||
ELAPSED_TIME=$(($SECONDS - $START_TIME))
|
||||
echo
|
||||
echo "The time of compilation is $(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
|
||||
else
|
||||
echo "ERROR: Makefile not found. This script requires the macx-clang makespec"
|
||||
exit
|
||||
fi
|
||||
|
||||
cp -R ${current_dir}/misc/Info.plist qelectrotech.app/Contents/
|
||||
cp -R ${current_dir}/ico/mac_icon/*.icns qelectrotech.app/Contents/Resources/
|
||||
# On rajoute le numero de version pour "cmd + i"
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION r$HEAD" "qelectrotech.app/Contents/Info.plist" # Version number
|
||||
|
||||
### copy over frameworks ############################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Copy Qt libraries and private frameworks:"
|
||||
|
||||
echo "Processing Mac deployment tool..."
|
||||
if [ ! -d $BUNDLE ] ; then
|
||||
echo "ERROR: cannot find application bundle \"$BUNDLE\" in current directory"
|
||||
exit
|
||||
fi
|
||||
#~/Qt/5.5/clang_64/bin/macdeployqt $BUNDLE
|
||||
macdeployqt $BUNDLE
|
||||
|
||||
### add file missing #######################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Copy file missing:"
|
||||
|
||||
# Dossier à ajouter
|
||||
QET_ELMT_DIR="${current_dir}/elements/"
|
||||
QET_TBT_DIR="${current_dir}/titleblocks/"
|
||||
QET_LANG_DIR="${current_dir}/lang/"
|
||||
QET_FONTS_DIR="${current_dir}/fonts/"
|
||||
QET_LICENSES_DIR="${current_dir}/licenses/"
|
||||
|
||||
# Add new folder for Qt dialog translation see
|
||||
## see <https://download.tuxfamily.org/qet/Qt_lang/>.
|
||||
|
||||
LANG_DIR="${current_dir}/lang1/"
|
||||
|
||||
if [ -d "${QET_ELMT_DIR}" ]; then
|
||||
echo "Copying add elements in the bundle..."
|
||||
#mkdir $BUNDLE/Contents/Resources/elements
|
||||
cp -R ${QET_ELMT_DIR} $BUNDLE/Contents/Resources/elements
|
||||
fi
|
||||
|
||||
if [ -d "${QET_TBT_DIR}" ]; then
|
||||
echo "Copying titleblocks in the bundle..."
|
||||
#mkdir $BUNDLE/Contents/Resources/titleblocks
|
||||
cp -R ${QET_TBT_DIR} $BUNDLE/Contents/Resources/titleblocks
|
||||
fi
|
||||
|
||||
if [ -d "${QET_LANG_DIR}" ]; then
|
||||
echo "Copying translations in the bundle... "
|
||||
mkdir $BUNDLE/Contents/Resources/lang
|
||||
cp ${current_dir}/lang/*.qm $BUNDLE/Contents/Resources/lang
|
||||
fi
|
||||
|
||||
if [ -d "${LANG_DIR}" ]; then
|
||||
echo "Copying translations in the bundle... "
|
||||
cp ${current_dir}/lang1/*.qm $BUNDLE/Contents/Resources/lang
|
||||
|
||||
fi
|
||||
|
||||
if [ -d "${QET_FONTS_DIR}" ]; then
|
||||
echo "Copying fonts in the bundle... "
|
||||
mkdir $BUNDLE/Contents/Resources/fonts
|
||||
cp ${current_dir}/fonts/*.ttf $BUNDLE/Contents/Resources/fonts
|
||||
|
||||
fi
|
||||
|
||||
if [ -d "${QET_LICENSES_DIR}" ]; then
|
||||
echo "Copying licenses in the bundle..."
|
||||
mkdir $BUNDLE/Contents/Resources/licenses
|
||||
cp -R -L ${QET_LICENSES_DIR} $BUNDLE/Contents/Resources/licenses
|
||||
fi
|
||||
### create disk image ###############################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Create disk image:"
|
||||
|
||||
# Direction
|
||||
EX_Dir="examples"
|
||||
DOC_Dir="docs/Documentation.webloc"
|
||||
imagedir="/tmp/$APPNAME.$$"
|
||||
|
||||
# Remove any previous disk folder or DMG
|
||||
echo 'Preparing (removing hold files)... '
|
||||
if [ -e "/Volumes/${APPNAME}" ]; then
|
||||
hdiutil detach -quiet "/Volumes/${APPNAME}"
|
||||
fi
|
||||
if [ -e "${APPNAME} $VERSION r$HEAD.dmg" ] ; then
|
||||
rm -f "${APPNAME} $VERSION r$HEAD.dmg"
|
||||
fi
|
||||
if [ -e "build-aux/mac-osx/${APPNAME} $VERSION r$HEAD.dmg" ] ; then
|
||||
rm -f "build-aux/mac-osx/${APPNAME} $VERSION r$HEAD.dmg"
|
||||
fi
|
||||
if [ -e $imagedir ] ; then
|
||||
rm -rf $imagedir
|
||||
fi
|
||||
|
||||
# Create disk folder
|
||||
echo 'Copying application bundle and examples... '
|
||||
mkdir $imagedir
|
||||
cp -Rf $BUNDLE $imagedir
|
||||
cp -Rf $EX_Dir $imagedir
|
||||
if [ -e $DOC_Dir ] ; then
|
||||
cp $DOC_Dir $imagedir
|
||||
else
|
||||
echo "Documentation in ${DOC_Dir} not find."
|
||||
fi
|
||||
ln -s /Applications $imagedir/Applications
|
||||
|
||||
# Elimine les accents, symbole ...
|
||||
strip "$imagedir/$APPBIN"
|
||||
|
||||
# Creating a disk image from a folder
|
||||
echo 'Creating disk image... '
|
||||
hdiutil create -quiet -ov -srcfolder $imagedir -format UDBZ -volname "${APPNAME}" "${APPNAME} $VERSION r$HEAD.dmg"
|
||||
hdiutil internet-enable -yes -quiet "${APPNAME} $VERSION r$HEAD.dmg"
|
||||
|
||||
# Clean up disk folder
|
||||
echo 'Cleaning up... '
|
||||
cp -Rf "${APPNAME} $VERSION r$HEAD.dmg" "build-aux/mac-osx/${APPNAME}-$VERSION-r$HEAD-intel_X86_64.dmg"
|
||||
rm -f "${APPNAME} $VERSION r$HEAD.dmg"
|
||||
rm -rf $imagedir
|
||||
rm -rf $BUNDLE
|
||||
|
||||
|
||||
### The end, process is done ##########################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "The process of creating deployable application bundle is done."
|
||||
echo The disque image is in the folder \'build-aux/mac-osx\'.
|
||||
# Affiche les mise à jour depuis l'ancienne revision
|
||||
#if [ ! $(($HEAD - $revAv)) -eq 0 ] ; then
|
||||
# echo
|
||||
# echo "There are new updates. This numero of revision is $HEAD."
|
||||
# svn log -l $(($HEAD - $revAv))
|
||||
#else
|
||||
# echo
|
||||
# echo "There are not new updates. This numero of revision is $HEAD."
|
||||
# fi
|
||||
# echo
|
||||
|
||||
# La version en local n'est pas conforme à la dernière version svn
|
||||
# svnversion | grep -q '[MS:]' ; if [ $? -eq 0 ] ; then
|
||||
# echo Please note that the latest \local version is $(svnversion).
|
||||
# echo This is not the same version as the deposit.
|
||||
# echo You can use \'svn diff\' to see the differences.
|
||||
# echo And use \'svn revert \<fichier\>\' to delete the difference.
|
||||
# echo To go back, you can use svn update -r 360
|
||||
# echo to go to revision number 360.
|
||||
# echo
|
||||
#fi
|
||||
|
||||
|
||||
|
||||
#rsync to TF DMG builds
|
||||
echo -e "\033[1;31mWould you like to upload MacOS packages "${APPNAME}"-"$VERSION"_"r$HEAD-intel.dmg", n/Y?.\033[m"
|
||||
read a
|
||||
if [[ $a == "Y" || $a == "y" ]]; then
|
||||
cp -Rf "build-aux/mac-osx/${APPNAME}-$VERSION-r$HEAD-intel_X86_64.dmg" /Users/laurent/MAC_OS_X/
|
||||
rsync -e ssh -av --delete-after --no-owner --no-g --chmod=g+w --progress --exclude='.DS_Store' /Users/laurent/MAC_OS_X/ server:download.qelectrotech.org/qet/builds/MAC_OS_X/intel_X86_64/
|
||||
if [ $? != 0 ]; then
|
||||
{
|
||||
echo "RSYNC ERROR: problem syncing ${APPNAME}-$VERSION-r$HEAD-intel_X86_64.dmg"
|
||||
rsync -e ssh -av --delete-after --no-owner --no-g --chmod=g+w --progress --exclude='.DS_Store' /Users/laurent/MAC_OS_X/ server:download.qelectrotech.org/qet/builds/MAC_OS_X/intel_X86_64/
|
||||
|
||||
} fi
|
||||
|
||||
else
|
||||
echo -e "\033[1;33mExit.\033[m"
|
||||
|
||||
fi
|
||||
@@ -1,509 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2023 The QElectroTech Team
|
||||
# This file is part of QElectroTech.
|
||||
|
||||
# QElectroTech is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# QElectroTech 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 General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
# Need homebrew and coreutils installed see <http://brew.sh>.
|
||||
|
||||
#Force MacOSX12.3.sdk
|
||||
#see: https://www.downtowndougbrown.com/2023/08/how-to-create-a-qt-5-arm-intel-universal-binary-for-mac/
|
||||
|
||||
export DEVELOPER_DIR=/Applications/Xcode_14.01.app/Contents/Developer
|
||||
|
||||
# configuration
|
||||
APPNAME='qelectrotech'
|
||||
BUNDLE=$APPNAME.app
|
||||
APPBIN="$BUNDLE/Contents/MacOS/$APPNAME"
|
||||
IDENTITY="Developer ID Application: Laurent TRINQUES (Y73WZ6WZ5X)"
|
||||
|
||||
# Temp paths
|
||||
RW_DMG="/tmp/qet_rw.dmg"
|
||||
MOUNT_POINT="/tmp/qet_dmg_mount"
|
||||
STAGING="/tmp/qet_dmg_staging"
|
||||
|
||||
# Script location
|
||||
current_dir=$(dirname "$0")
|
||||
|
||||
# Go back to repo root
|
||||
cd "${current_dir}/../"
|
||||
|
||||
# Current directory
|
||||
current_dir=$(PWD)
|
||||
|
||||
|
||||
### get system configuration ########################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "This script prepares a Qt application bundle for deployment."
|
||||
echo "Please see the \"Deploying an Application on Qt/Mac\""
|
||||
echo "page in the Qt documentation for more information."
|
||||
echo
|
||||
echo "This script :"
|
||||
echo "\t - update the git depot"
|
||||
echo "\t - build the application bundle,"
|
||||
echo "\t - copy over required Qt frameworks,"
|
||||
echo "\t - copy additional files: translations, titleblocks and elements,"
|
||||
echo "\t - notarize the .app, then create a signed DMG."
|
||||
echo
|
||||
echo "Enjoy ;-)"
|
||||
echo
|
||||
|
||||
# as long as we can find qmake, we don't need QTDIR
|
||||
FWPATH=`qmake -query QT_INSTALL_LIBS`
|
||||
if [ ! -d $FWPATH/QtGui.framework ] ; then
|
||||
echo "ERROR: cannot find the Qt frameworks. Make sure Qt is installed"
|
||||
echo "and qmake is in your environment path."
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
### GIT ####################################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Run GIT:"
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
git pull --recurse-submodules
|
||||
git pull
|
||||
|
||||
# Get revision number and version
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
A=$(git rev-list HEAD --count)
|
||||
HEAD=$(($A+473))
|
||||
|
||||
VERSION=$(cat sources/qetversion.cpp | grep "return QVersionNumber{"| head -n 1| awk -F "{" '{ print $2 }' | awk -F "}" '{ print $1 }' | sed -e 's/,/./g' -e 's/ //g')
|
||||
|
||||
DMG_NAME="${APPNAME}-$VERSION-r$HEAD-arm64.dmg"
|
||||
DMG_PATH="build-aux/mac-osx/$DMG_NAME"
|
||||
|
||||
# Check if already built
|
||||
if [ -e "$DMG_PATH" ] ; then
|
||||
echo "There are not new updates, make disk image can"
|
||||
echo "take a lot of time (5 min). Can you continu?"
|
||||
echo "[y/n]"
|
||||
read userinput
|
||||
if [ "$userinput" == "n" ] ; then
|
||||
echo
|
||||
echo "Process is stopped."
|
||||
echo
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
### make install ####################################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Run make install:"
|
||||
|
||||
# Remove old bundle
|
||||
if [ -d $BUNDLE ] ; then
|
||||
echo "Removing old bundle..."
|
||||
rm -rf $BUNDLE
|
||||
fi
|
||||
if [ -e Makefile ] ; then
|
||||
echo "Removing old Makefile..."
|
||||
rm .qmake.stash
|
||||
make clean
|
||||
fi
|
||||
|
||||
# Generate Makefile
|
||||
echo "Generating new makefile..."
|
||||
qmake -spec macx-clang
|
||||
|
||||
# Compile
|
||||
if [ -e Makefile.Release ] ; then
|
||||
START_TIME=$SECONDS
|
||||
|
||||
testSuccessBuild () {
|
||||
if [ $? -ne 0 ]; then
|
||||
cleanVerionTag
|
||||
ELAPSED_TIME=$(($SECONDS - $START_TIME))
|
||||
echo
|
||||
echo "make failed - $(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
coeur=$(sysctl hw.ncpu | awk '{print $2}')
|
||||
if [ $? -ne 0 ]; then
|
||||
make -f Makefile.Release
|
||||
testSuccessBuild
|
||||
else
|
||||
make -j$(($coeur + 1)) -f Makefile.Release
|
||||
testSuccessBuild
|
||||
fi
|
||||
|
||||
ELAPSED_TIME=$(($SECONDS - $START_TIME))
|
||||
echo
|
||||
echo "The time of compilation is $(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
|
||||
else
|
||||
echo "ERROR: Makefile not found. This script requires the macx-clang makespec"
|
||||
exit
|
||||
fi
|
||||
|
||||
cp -R ${current_dir}/misc/Info.plist qelectrotech.app/Contents/
|
||||
cp -R ${current_dir}/ico/mac_icon/*.icns qelectrotech.app/Contents/Resources/
|
||||
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION r$HEAD" "qelectrotech.app/Contents/Info.plist"
|
||||
|
||||
|
||||
### copy over frameworks ############################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Copy Qt libraries and private frameworks:"
|
||||
|
||||
echo "Processing Mac deployment tool..."
|
||||
if [ ! -d $BUNDLE ] ; then
|
||||
echo "ERROR: cannot find application bundle \"$BUNDLE\" in current directory"
|
||||
exit
|
||||
fi
|
||||
macdeployqt $BUNDLE
|
||||
|
||||
### add missing files ###############################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Copy missing files:"
|
||||
|
||||
QET_ELMT_DIR="${current_dir}/elements/"
|
||||
QET_TBT_DIR="${current_dir}/titleblocks/"
|
||||
QET_LANG_DIR="${current_dir}/lang/"
|
||||
QET_EXAMPLES_DIR="${current_dir}/examples/"
|
||||
QET_FONTS_DIR="${current_dir}/fonts/"
|
||||
QET_LICENSES_DIR="${current_dir}/licenses/"
|
||||
LANG_DIR="${current_dir}/lang1/"
|
||||
|
||||
if [ -d "${QET_ELMT_DIR}" ]; then
|
||||
echo "Copying elements in the bundle..."
|
||||
cp -R ${QET_ELMT_DIR} $BUNDLE/Contents/Resources/elements
|
||||
fi
|
||||
|
||||
if [ -d "${QET_TBT_DIR}" ]; then
|
||||
echo "Copying titleblocks in the bundle..."
|
||||
cp -R ${QET_TBT_DIR} $BUNDLE/Contents/Resources/titleblocks
|
||||
fi
|
||||
|
||||
if [ -d "${QET_LANG_DIR}" ]; then
|
||||
echo "Copying translations in the bundle..."
|
||||
mkdir $BUNDLE/Contents/Resources/lang
|
||||
cp ${current_dir}/lang/*.qm $BUNDLE/Contents/Resources/lang
|
||||
fi
|
||||
|
||||
if [ -d "${LANG_DIR}" ]; then
|
||||
echo "Copying extra translations in the bundle..."
|
||||
cp ${current_dir}/lang1/*.qm $BUNDLE/Contents/Resources/lang
|
||||
fi
|
||||
|
||||
if [ -d "${QET_EXAMPLES_DIR}" ]; then
|
||||
echo "Copying examples in the bundle..."
|
||||
mkdir $BUNDLE/Contents/Resources/examples
|
||||
cp ${current_dir}/examples/*.qet $BUNDLE/Contents/Resources/examples
|
||||
fi
|
||||
|
||||
if [ -d "${QET_FONTS_DIR}" ]; then
|
||||
echo "Copying fonts in the bundle..."
|
||||
mkdir $BUNDLE/Contents/Resources/fonts
|
||||
cp ${current_dir}/fonts/*.ttf $BUNDLE/Contents/Resources/fonts
|
||||
fi
|
||||
|
||||
if [ -d "${QET_LICENSES_DIR}" ]; then
|
||||
echo "Copying licenses in the bundle..."
|
||||
mkdir $BUNDLE/Contents/Resources/licenses
|
||||
cp -R -L ${QET_LICENSES_DIR} $BUNDLE/Contents/Resources/licenses
|
||||
fi
|
||||
|
||||
### Sign the bundle #################################################
|
||||
# Sign in correct order: all dylibs first (including flat libs copied
|
||||
# by macdeployqt from Homebrew), then frameworks, plugins, bundle last.
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Code signing (dylibs -> frameworks -> plugins -> bundle):"
|
||||
|
||||
# 1. Sign all flat .dylib files in Frameworks/
|
||||
echo "-- Signing dylibs in Frameworks/..."
|
||||
find "$BUNDLE/Contents/Frameworks" -name "*.dylib" | while read lib; do
|
||||
echo " $(basename $lib)"
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$lib"
|
||||
done
|
||||
|
||||
# 2. Sign .framework bundles
|
||||
echo "-- Signing .framework bundles..."
|
||||
find "$BUNDLE/Contents/Frameworks" -maxdepth 1 -name "*.framework" | while read fw; do
|
||||
echo " $(basename $fw)"
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$fw"
|
||||
done
|
||||
|
||||
# 3. Sign plugins
|
||||
echo "-- Signing plugins..."
|
||||
find "$BUNDLE/Contents/PlugIns" \( -name "*.dylib" -o -name "*.so" \) | while read lib; do
|
||||
echo " $(basename $lib)"
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$lib"
|
||||
done
|
||||
|
||||
# 4. Sign any dylibs in MacOS/
|
||||
echo "-- Signing dylibs in MacOS/..."
|
||||
find "$BUNDLE/Contents/MacOS" -name "*.dylib" | while read lib; do
|
||||
echo " $(basename $lib)"
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$lib"
|
||||
done
|
||||
|
||||
# 5. Sign the main executable explicitly
|
||||
echo "-- Signing main executable..."
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime \
|
||||
"$BUNDLE/Contents/MacOS/$APPNAME"
|
||||
|
||||
# 6. Sign the bundle itself last
|
||||
echo "-- Signing bundle..."
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$BUNDLE"
|
||||
|
||||
# 7. Verify
|
||||
echo
|
||||
echo "Verifying bundle signature..."
|
||||
codesign --verify --deep --strict --verbose=2 "$BUNDLE"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: bundle signature verification failed, aborting."
|
||||
exit 1
|
||||
fi
|
||||
spctl -a -vv "$BUNDLE"
|
||||
echo "Bundle signature OK."
|
||||
|
||||
### Notarize the .app (via temporary ZIP) ###########################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Create temporary ZIP for notarization:"
|
||||
|
||||
NOTARIZE_ZIP="/tmp/${APPNAME}-$VERSION-r$HEAD-arm64-notarize.zip"
|
||||
/usr/bin/ditto -c -k --keepParent "$BUNDLE" "$NOTARIZE_ZIP"
|
||||
|
||||
echo -e "\033[1;31mWould you like to notarize the .app \"${APPNAME}-${VERSION}-r${HEAD}\", n/Y?\033[m"
|
||||
read a
|
||||
if [[ $a == "Y" || $a == "y" ]]; then
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Notarizing .app:"
|
||||
xcrun notarytool submit "$NOTARIZE_ZIP" --keychain-profile "org.qelectrotech" --wait
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: notarization failed. Check the log with:"
|
||||
echo " xcrun notarytool log <submission-id> --keychain-profile org.qelectrotech"
|
||||
rm -f "$NOTARIZE_ZIP"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "\033[1;33mExit.\033[m"
|
||||
fi
|
||||
|
||||
echo "Cleaning up temporary notarization ZIP..."
|
||||
rm -f "$NOTARIZE_ZIP"
|
||||
|
||||
### Staple the .app #################################################
|
||||
|
||||
echo -e "\033[1;31mWould you like to staple the .app \"${APPNAME}-${VERSION}-r${HEAD}\", n/Y?\033[m"
|
||||
read a
|
||||
if [[ $a == "Y" || $a == "y" ]]; then
|
||||
xcrun stapler staple -v "$BUNDLE"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: stapling .app failed."
|
||||
exit 1
|
||||
fi
|
||||
echo "Verifying staple on .app..."
|
||||
xcrun stapler validate -v "$BUNDLE"
|
||||
spctl -a -vv "$BUNDLE"
|
||||
echo ".app stapled OK."
|
||||
else
|
||||
echo -e "\033[1;33mExit.\033[m"
|
||||
fi
|
||||
|
||||
### Create staging folder with Applications symlink #################
|
||||
# The staging folder contains the .app and a symlink to /Applications
|
||||
# so the user can drag-and-drop to install directly from the DMG.
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Preparing DMG staging folder:"
|
||||
|
||||
rm -rf "$STAGING"
|
||||
mkdir -p "$STAGING"
|
||||
cp -R "$BUNDLE" "$STAGING/"
|
||||
ln -s /Applications "$STAGING/Applications"
|
||||
echo "Staging folder ready: $STAGING"
|
||||
|
||||
### Create writable DMG (UDRW) ######################################
|
||||
# We use a writable DMG first so we can re-sign the .app inside
|
||||
# after hdiutil copies it (hdiutil can invalidate Sealed Resources
|
||||
# during the copy, so we must re-sign inside the mounted volume).
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Create writable DMG (UDRW) and re-sign .app inside:"
|
||||
|
||||
rm -f "$RW_DMG"
|
||||
hdiutil create \
|
||||
-volname "QElectroTech $VERSION" \
|
||||
-srcfolder "$STAGING" \
|
||||
-ov \
|
||||
-format UDRW \
|
||||
-fs HFS+ \
|
||||
"$RW_DMG"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: hdiutil failed to create writable DMG."
|
||||
rm -rf "$STAGING"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Mount the writable DMG
|
||||
rm -rf "$MOUNT_POINT"
|
||||
mkdir -p "$MOUNT_POINT"
|
||||
hdiutil attach "$RW_DMG" -mountpoint "$MOUNT_POINT" -nobrowse -noverify
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: failed to mount writable DMG."
|
||||
rm -f "$RW_DMG"
|
||||
rm -rf "$STAGING"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Re-sign all binaries inside the mounted DMG
|
||||
echo "-- Re-signing dylibs inside DMG..."
|
||||
find "$MOUNT_POINT/$BUNDLE/Contents/Frameworks" -name "*.dylib" | while read lib; do
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$lib"
|
||||
done
|
||||
|
||||
find "$MOUNT_POINT/$BUNDLE/Contents/Frameworks" -maxdepth 1 -name "*.framework" | while read fw; do
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$fw"
|
||||
done
|
||||
|
||||
find "$MOUNT_POINT/$BUNDLE/Contents/PlugIns" \( -name "*.dylib" -o -name "*.so" \) | while read lib; do
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime "$lib"
|
||||
done
|
||||
|
||||
echo "-- Re-signing main executable inside DMG..."
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime \
|
||||
"$MOUNT_POINT/$BUNDLE/Contents/MacOS/$APPNAME"
|
||||
|
||||
echo "-- Re-signing bundle inside DMG..."
|
||||
codesign --force --sign "$IDENTITY" --timestamp --options=runtime \
|
||||
"$MOUNT_POINT/$BUNDLE"
|
||||
|
||||
# Verify signature inside the mounted DMG
|
||||
echo "Verifying bundle signature inside DMG..."
|
||||
codesign --verify --deep --strict --verbose=2 "$MOUNT_POINT/$BUNDLE"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: bundle signature invalid inside DMG, aborting."
|
||||
hdiutil detach "$MOUNT_POINT"
|
||||
rm -f "$RW_DMG"
|
||||
rm -rf "$STAGING" "$MOUNT_POINT"
|
||||
exit 1
|
||||
fi
|
||||
echo "Bundle signature inside DMG OK."
|
||||
|
||||
# Detach the writable DMG
|
||||
hdiutil detach "$MOUNT_POINT"
|
||||
|
||||
### Convert UDRW to final compressed UDZO ###########################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Convert to final compressed DMG (UDZO):"
|
||||
|
||||
mkdir -p "build-aux/mac-osx"
|
||||
rm -f "$DMG_PATH"
|
||||
|
||||
hdiutil convert "$RW_DMG" \
|
||||
-format UDZO \
|
||||
-o "$DMG_PATH"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: hdiutil convert failed."
|
||||
rm -f "$RW_DMG"
|
||||
rm -rf "$STAGING" "$MOUNT_POINT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$RW_DMG"
|
||||
rm -rf "$STAGING" "$MOUNT_POINT"
|
||||
|
||||
### Sign the final DMG ##############################################
|
||||
|
||||
echo "Signing final DMG..."
|
||||
codesign --sign "$IDENTITY" --timestamp "$DMG_PATH"
|
||||
|
||||
### Notarize and staple the final DMG ###############################
|
||||
|
||||
echo -e "\033[1;31mWould you like to notarize the DMG \"${DMG_NAME}\", n/Y?\033[m"
|
||||
read a
|
||||
if [[ $a == "Y" || $a == "y" ]]; then
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Notarizing DMG:"
|
||||
xcrun notarytool submit "$DMG_PATH" --keychain-profile "org.qelectrotech" --wait
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: DMG notarization failed. Check the log with:"
|
||||
echo " xcrun notarytool log <submission-id> --keychain-profile org.qelectrotech"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Stapling DMG..."
|
||||
xcrun stapler staple "$DMG_PATH"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: stapling DMG failed."
|
||||
exit 1
|
||||
fi
|
||||
echo "DMG notarized and stapled OK."
|
||||
|
||||
echo "Verifying final DMG..."
|
||||
spctl -a -vv "$DMG_PATH"
|
||||
else
|
||||
echo -e "\033[1;33mExit.\033[m"
|
||||
fi
|
||||
|
||||
### Clean up bundle #################################################
|
||||
|
||||
echo "Cleaning up bundle..."
|
||||
rm -rf "$BUNDLE"
|
||||
|
||||
### The end #########################################################
|
||||
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "The process is done."
|
||||
echo "DMG is in the folder 'build-aux/mac-osx'."
|
||||
|
||||
### Upload via rsync ################################################
|
||||
|
||||
echo -e "\033[1;31mWould you like to upload MacOS package \"${DMG_NAME}\", n/Y?\033[m"
|
||||
read a
|
||||
if [[ $a == "Y" || $a == "y" ]]; then
|
||||
cp -Rf "$DMG_PATH" /Users/laurent/MAC_OS_X/
|
||||
rsync -e ssh -av --delete-after --no-owner --no-g --chmod=g+w \
|
||||
--progress --exclude='.DS_Store' \
|
||||
/Users/laurent/MAC_OS_X/ \
|
||||
server:download.qelectrotech.org/qet/builds/MAC_OS_X/arm64/
|
||||
if [ $? != 0 ]; then
|
||||
echo "RSYNC ERROR: problem syncing ${DMG_NAME}, retrying..."
|
||||
rsync -e ssh -av --delete-after --no-owner --no-g --chmod=g+w \
|
||||
--progress --exclude='.DS_Store' \
|
||||
/Users/laurent/MAC_OS_X/ \
|
||||
server:download.qelectrotech.org/qet/builds/MAC_OS_X/arm64/
|
||||
fi
|
||||
else
|
||||
echo -e "\033[1;33mExit.\033[m"
|
||||
fi
|
||||
@@ -126,7 +126,8 @@ ELAPSED_TIME=$(($SECONDS - $START_TIME))
|
||||
echo
|
||||
echo "The time of compilation is $(($ELAPSED_TIME/60)) min $(($ELAPSED_TIME%60)) sec"
|
||||
|
||||
# TODO: confirmer le chemin exact de sortie du .app selon CMakeLists.txt
|
||||
# Le .app sort a la racine de $BUILD_DIR : add_executable(... MACOSX_BUNDLE)
|
||||
# sans RUNTIME_OUTPUT_DIRECTORY dans CMakeLists.txt.
|
||||
echo "Copying built bundle into place..."
|
||||
cp -R "$BUILD_DIR/qelectrotech.app" "./$BUNDLE"
|
||||
|
||||
@@ -147,6 +148,98 @@ fi
|
||||
|
||||
macdeployqt $BUNDLE
|
||||
|
||||
### fix Homebrew dependencies macdeployqt could not handle ##########
|
||||
# Recent Homebrew bottles (brotli, webp, sharpyuv...) reference their own
|
||||
# dependencies as @rpath/libX.dylib. macdeployqt only resolves @rpath in
|
||||
# Contents/lib and in Qt's lib dir (-libpath does not help): it prints
|
||||
# "Cannot resolve rpath" and leaves some references untouched, either
|
||||
# absolute /opt/homebrew paths or @rpath libs missing from the bundle.
|
||||
# Fix both here: every /opt/homebrew reference is rewritten to
|
||||
# @rpath/libX.dylib (install ids too), and every @rpath/libX.dylib is
|
||||
# copied into Contents/Frameworks, where the executable's LC_RPATH
|
||||
# (@executable_path/../Frameworks) lets dyld find it. Everything is signed
|
||||
# below with the rest of Frameworks/.
|
||||
echo
|
||||
echo "______________________________________________________________"
|
||||
echo "Fix Homebrew dependencies left by macdeployqt:"
|
||||
|
||||
FW="$BUNDLE/Contents/Frameworks"
|
||||
chmod -R u+w "$BUNDLE/Contents/MacOS" "$FW" "$BUNDLE/Contents/PlugIns" 2>/dev/null
|
||||
|
||||
# Every Mach-O candidate of the bundle (otool silently ignores the others)
|
||||
list_macho() {
|
||||
find "$BUNDLE/Contents/MacOS" "$FW" "$BUNDLE/Contents/PlugIns" -type f \
|
||||
\( -name '*.dylib' -o -perm -u+x \) 2>/dev/null
|
||||
}
|
||||
|
||||
# Dependencies of one binary, without its own install id (dylibs only)
|
||||
list_deps() {
|
||||
_id=$(otool -D "$1" 2>/dev/null | sed -n 2p)
|
||||
otool -L "$1" 2>/dev/null | awk 'NR>1 { print $1 }' | while read _dep; do
|
||||
[ "$_dep" = "$_id" ] || echo "$_dep"
|
||||
done
|
||||
}
|
||||
|
||||
# The @rpath/libX.dylib names referenced anywhere in the bundle
|
||||
list_rpath_libs() {
|
||||
list_macho | while read bin; do
|
||||
list_deps "$bin" | sed -n 's#^@rpath/\([^/]*\.dylib\)$#\1#p'
|
||||
done | LC_ALL=C sort -u
|
||||
}
|
||||
|
||||
if ! otool -l "$BUNDLE/Contents/MacOS/$APPNAME" | grep -q "@executable_path/../Frameworks" ; then
|
||||
install_name_tool -add_rpath "@executable_path/../Frameworks" "$BUNDLE/Contents/MacOS/$APPNAME"
|
||||
echo " Added LC_RPATH @executable_path/../Frameworks to $APPNAME"
|
||||
fi
|
||||
|
||||
# 3 passes, since each copied library can bring its own dependencies:
|
||||
# a. rewrite absolute /opt/homebrew references (install ids included),
|
||||
# copying the referenced library into Frameworks/ if needed
|
||||
# b. copy the @rpath/libX.dylib still missing from Frameworks/
|
||||
for PASS in 1 2 3; do
|
||||
list_macho | while read bin; do
|
||||
_id=$(otool -D "$bin" 2>/dev/null | sed -n 2p)
|
||||
case "$_id" in
|
||||
/opt/homebrew/*)
|
||||
install_name_tool -id "@rpath/$(basename "$_id")" "$bin" 2>/dev/null
|
||||
echo " Fixed id (pass $PASS): $(basename "$bin")"
|
||||
;;
|
||||
esac
|
||||
list_deps "$bin" | grep '^/opt/homebrew/' | while read ref; do
|
||||
name=$(basename "$ref")
|
||||
if [ ! -e "$FW/$name" ]; then
|
||||
cp -L "$ref" "$FW/$name" && chmod u+w "$FW/$name"
|
||||
echo " Copied (pass $PASS): $name"
|
||||
fi
|
||||
install_name_tool -change "$ref" "@rpath/$name" "$bin" 2>/dev/null
|
||||
echo " Fixed ref (pass $PASS): $(basename "$bin") -> @rpath/$name"
|
||||
done
|
||||
done
|
||||
list_rpath_libs | while read lib; do
|
||||
if [ ! -e "$FW/$lib" ] && [ -e "/opt/homebrew/lib/$lib" ]; then
|
||||
cp -L "/opt/homebrew/lib/$lib" "$FW/$lib" && chmod u+w "$FW/$lib"
|
||||
echo " Copied (pass $PASS): $lib"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# 3. Checks
|
||||
UNRESOLVED=$(list_rpath_libs | while read lib; do [ -e "$FW/$lib" ] || echo "$lib"; done)
|
||||
if [ -n "$UNRESOLVED" ]; then
|
||||
echo "ERROR: @rpath libraries still missing from Frameworks/:" $UNRESOLVED
|
||||
exit 1
|
||||
fi
|
||||
HOMEBREW_REFS=$(list_macho | while read bin; do
|
||||
otool -L "$bin" 2>/dev/null | awk 'NR>1 { print $1 }' | grep '^/opt/homebrew/' \
|
||||
| sed "s#^# $(basename "$bin") -> #"
|
||||
done)
|
||||
if [ -n "$HOMEBREW_REFS" ]; then
|
||||
echo "ERROR: bundle still references Homebrew paths:"
|
||||
echo "$HOMEBREW_REFS"
|
||||
exit 1
|
||||
fi
|
||||
echo "All dependencies resolved inside the bundle."
|
||||
|
||||
### install Info.plist and app icon #################################
|
||||
# NOTE: this must run AFTER macdeployqt, not before. macdeployqt
|
||||
# rewrites/regenerates parts of Contents/Resources, and files copied
|
||||
@@ -175,7 +268,6 @@ QET_LANG_DIR="${current_dir}/lang/"
|
||||
QET_EXAMPLES_DIR="${current_dir}/examples/"
|
||||
QET_FONTS_DIR="${current_dir}/fonts/"
|
||||
QET_LICENSES_DIR="${current_dir}/licenses/"
|
||||
LANG_DIR="${current_dir}/lang1/"
|
||||
|
||||
if [ -d "${QET_ELMT_DIR}" ]; then
|
||||
cp -R ${QET_ELMT_DIR} $BUNDLE/Contents/Resources/elements
|
||||
@@ -183,12 +275,85 @@ fi
|
||||
if [ -d "${QET_TBT_DIR}" ]; then
|
||||
cp -R ${QET_TBT_DIR} $BUNDLE/Contents/Resources/titleblocks
|
||||
fi
|
||||
if [ -d "${QET_LANG_DIR}" ]; then
|
||||
mkdir $BUNDLE/Contents/Resources/lang
|
||||
cp ${current_dir}/lang/*.qm $BUNDLE/Contents/Resources/lang
|
||||
# Traductions : depuis la PR #751, les .qm ne sont plus versionnes ; lrelease
|
||||
# les genere dans $BUILD_DIR/lang/. Jeu attendu = les .ts listes dans TS_FILES
|
||||
# (cmake/qet_compilation_vars.cmake) : un .qm manquant arrete le script, un
|
||||
# .ts present dans lang/ mais absent de TS_FILES donne seulement un WARNING.
|
||||
# Fichiers temporaires plutot que <(...) : /bin/sh de macOS (bash 3.2 en mode
|
||||
# POSIX) n'a pas la substitution de processus.
|
||||
QM_SRC="${current_dir}/${BUILD_DIR}/lang"
|
||||
QM_TMP=$(mktemp -d /tmp/qet_qm.XXXXXX)
|
||||
grep -o 'lang/qet_[A-Za-z_]*\.ts' "${current_dir}/cmake/qet_compilation_vars.cmake" \
|
||||
| sed -e 's#^lang/##' -e 's#\.ts$##' | LC_ALL=C sort -u > "$QM_TMP/listed"
|
||||
if [ ! -s "$QM_TMP/listed" ]; then
|
||||
echo "ERROR: cannot read TS_FILES from cmake/qet_compilation_vars.cmake"
|
||||
rm -rf "$QM_TMP"
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "${LANG_DIR}" ]; then
|
||||
cp ${current_dir}/lang1/*.qm $BUNDLE/Contents/Resources/lang
|
||||
find "${QET_LANG_DIR}" -maxdepth 1 -name 'qet_*.ts' -exec basename {} .ts \; | LC_ALL=C sort > "$QM_TMP/present"
|
||||
UNLISTED=$(LC_ALL=C comm -13 "$QM_TMP/listed" "$QM_TMP/present")
|
||||
if [ -n "$UNLISTED" ]; then
|
||||
echo "WARNING: .ts files not in TS_FILES, no .qm built:" $UNLISTED
|
||||
fi
|
||||
mkdir -p $BUNDLE/Contents/Resources/lang
|
||||
find "${QM_SRC}" -maxdepth 1 -name 'qet_*.qm' -exec cp {} $BUNDLE/Contents/Resources/lang/ \; 2>/dev/null
|
||||
find $BUNDLE/Contents/Resources/lang -maxdepth 1 -name 'qet_*.qm' -exec basename {} .qm \; | LC_ALL=C sort > "$QM_TMP/built"
|
||||
MISSING=$(LC_ALL=C comm -23 "$QM_TMP/listed" "$QM_TMP/built")
|
||||
echo "$(wc -l < "$QM_TMP/built" | tr -d ' ') .qm files copied to Contents/Resources/lang (expected: $(wc -l < "$QM_TMP/listed" | tr -d ' '))"
|
||||
|
||||
# Traductions de Qt lui-meme (boutons OK/Annuler, dialogues standard...) :
|
||||
# elles viennent de qtbase_XX.qm, pas des .ts de QET, et macdeployqt ne les
|
||||
# deploie pas. QETApp::setLanguage() charge "qt_XX" depuis le chemin de
|
||||
# traductions de Qt (absent du bundle), puis depuis le dossier lang/ de QET :
|
||||
# on y depose donc chaque qtbase_XX.qm sous le nom qt_XX.qm. qtbase_XX.qm est
|
||||
# autonome, contrairement aux qt_XX.qm de Qt qui dependent de tous les modules.
|
||||
# Premier dossier contenant des qtbase_*.qm : celui annonce par qtpaths, puis
|
||||
# la formule Homebrew separee qttranslations, puis les autres emplacements
|
||||
# Homebrew possibles. Homebrew fait de ces dossiers des liens symboliques
|
||||
# (-> Cellar/qttranslations/...) : find doit donc les suivre (-L), sinon il
|
||||
# ne voit que le lien lui-meme et ne trouve aucun fichier dedans.
|
||||
QT_TR_DIR=""
|
||||
for d in "$("$QT_PREFIX/bin/qtpaths" --query QT_INSTALL_TRANSLATIONS 2>/dev/null)" \
|
||||
"$(brew --prefix qttranslations 2>/dev/null)/share/qt/translations" \
|
||||
"$QT_PREFIX/share/qt/translations" \
|
||||
/opt/homebrew/share/qt/translations \
|
||||
/opt/homebrew/opt/*/share/qt/translations ; do
|
||||
if ls "$d"/qtbase_*.qm >/dev/null 2>&1 ; then
|
||||
QT_TR_DIR="$d"
|
||||
break
|
||||
fi
|
||||
done
|
||||
LANG_DST="$BUNDLE/Contents/Resources/lang"
|
||||
find -L "$QT_TR_DIR" -maxdepth 1 -name 'qtbase_*.qm' 2>/dev/null | while read f; do
|
||||
l=$(basename "$f" .qm | sed 's/^qtbase_//')
|
||||
cp "$f" "$LANG_DST/qt_$l.qm"
|
||||
done
|
||||
# Langues QET sans equivalent Qt exact (pt -> pt_PT, zh -> zh_CN...) :
|
||||
# QTranslator ne sait que raccourcir le code (fr_FR -> fr), pas l'allonger.
|
||||
# On prefere la variante "principale" (pt_PT), sinon la premiere trouvee.
|
||||
sed 's/^qet_//' "$QM_TMP/listed" | while read l; do
|
||||
if [ ! -e "$LANG_DST/qt_$l.qm" ]; then
|
||||
main="$QT_TR_DIR/qtbase_${l}_$(echo "$l" | tr 'a-z' 'A-Z').qm"
|
||||
if [ -e "$main" ]; then
|
||||
alt="$main"
|
||||
else
|
||||
alt=$(find -L "$QT_TR_DIR" -maxdepth 1 -name "qtbase_${l}_*.qm" 2>/dev/null | LC_ALL=C sort | head -1)
|
||||
fi
|
||||
[ -n "$alt" ] && cp "$alt" "$LANG_DST/qt_$l.qm"
|
||||
fi
|
||||
done
|
||||
QT_QM_COUNT=$(find "$LANG_DST" -maxdepth 1 -name 'qt_*.qm' | wc -l | tr -d ' ')
|
||||
echo "${QT_QM_COUNT} Qt translation files (qt_*.qm) copied from ${QT_TR_DIR:-<not found>}"
|
||||
if [ "${QT_QM_COUNT}" -eq 0 ]; then
|
||||
echo "ERROR: no qtbase_*.qm found (Qt translations not installed?)."
|
||||
echo " Check with: find /opt/homebrew -name 'qtbase_fr.qm'"
|
||||
rm -rf "$QM_TMP"
|
||||
exit 1
|
||||
fi
|
||||
rm -rf "$QM_TMP"
|
||||
if [ -n "$MISSING" ]; then
|
||||
echo "ERROR: missing translations:" $MISSING
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "${QET_EXAMPLES_DIR}" ]; then
|
||||
mkdir $BUNDLE/Contents/Resources/examples
|
||||
|
||||
@@ -1,381 +0,0 @@
|
||||
######################################################################
|
||||
# Fichier projet de QElectroTech #
|
||||
######################################################################
|
||||
|
||||
# Chemins utilises pour la compilation et l'installation de QET
|
||||
unix {
|
||||
# Chemins UNIX
|
||||
COMPIL_PREFIX = '/usr/local/'
|
||||
INSTALL_PREFIX = '/usr/local/'
|
||||
QET_BINARY_PATH = 'bin/'
|
||||
QET_COMMON_COLLECTION_PATH = 'share/qelectrotech/elements/'
|
||||
QET_COMMON_TBT_PATH = 'share/qelectrotech/titleblocks/'
|
||||
QET_LANG_PATH = 'share/qelectrotech/lang/'
|
||||
QET_EXAMPLES_PATH = 'share/qelectrotech/examples/'
|
||||
QET_LICENSE_PATH = 'doc/qelectrotech/'
|
||||
QET_MIME_PACKAGE_PATH = '../share/mime/packages/'
|
||||
QET_DESKTOP_PATH = 'share/applications/'
|
||||
QET_ICONS_PATH = 'share/icons/hicolor/'
|
||||
QET_MAN_PATH = 'man/'
|
||||
QET_APPDATA_PATH = 'share/appdata'
|
||||
}
|
||||
win32 {
|
||||
# Chemins Windows
|
||||
COMPIL_PREFIX = './'
|
||||
INSTALL_PREFIX = './'
|
||||
QET_BINARY_PATH = './'
|
||||
QET_COMMON_COLLECTION_PATH = 'elements/'
|
||||
QET_COMMON_TBT_PATH = 'titleblocks/'
|
||||
QET_LANG_PATH = 'lang/'
|
||||
QET_LICENSE_PATH = './'
|
||||
# Liste des ressources Windows
|
||||
#RC_FILE = qelectrotech.rc
|
||||
}
|
||||
macx {
|
||||
# Chemins MacOS X
|
||||
COMPIL_PREFIX = './'
|
||||
INSTALL_PREFIX = '/usr/local/'
|
||||
QET_BINARY_PATH = 'bin/'
|
||||
QET_COMMON_COLLECTION_PATH = '../Resources/elements/'
|
||||
QET_COMMON_TBT_PATH = '../Resources/titleblocks/'
|
||||
QET_LANG_PATH = '../Resources/lang/'
|
||||
QET_EXAMPLES_PATH = 'share/qelectrotech/examples/'
|
||||
QET_LICENSE_PATH = 'doc/qelectrotech/'
|
||||
QET_DESKTOP_PATH = 'share/applications/'
|
||||
QET_ICONS_PATH = 'share/icons/hicolor/'
|
||||
QET_MAN_PATH = 'man/'
|
||||
ICON = 'ico/mac_icon/qelectrotech.icns'
|
||||
|
||||
}
|
||||
|
||||
# Commenter la ligne ci-dessous pour desactiver l'option --common-elements-dir
|
||||
DEFINES += QET_ALLOW_OVERRIDE_CED_OPTION
|
||||
|
||||
# Comment the line below to disable the --common-tbt-dir option
|
||||
DEFINES += QET_ALLOW_OVERRIDE_CTBTD_OPTION
|
||||
|
||||
# Commenter la ligne ci-dessous pour desactiver l'option --config-dir
|
||||
DEFINES += QET_ALLOW_OVERRIDE_CD_OPTION
|
||||
|
||||
# Commenter la ligne ci-dessous pour desactiver l'option --data-dir
|
||||
DEFINES += QET_ALLOW_OVERRIDE_DD_OPTION
|
||||
|
||||
#comment the line below to disable the project database export
|
||||
DEFINES += QET_EXPORT_PROJECT_DB
|
||||
|
||||
# warn on *any* usage of deprecated APIs
|
||||
#DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
|
||||
######################################################################
|
||||
|
||||
include(sources/PropertiesEditor/PropertiesEditor.pri)
|
||||
include(sources/QetGraphicsItemModeler/QetGraphicsItemModeler.pri)
|
||||
include(sources/QPropertyUndoCommand/QPropertyUndoCommand.pri)
|
||||
include(SingleApplication/singleapplication.pri)
|
||||
include(sources/QWidgetAnimation/QWidgetAnimation.pri)
|
||||
|
||||
DEFINES += QAPPLICATION_CLASS=QApplication
|
||||
DEFINES += QT_MESSAGELOGCONTEXT
|
||||
DEFINES += GIT_COMMIT_SHA="\\\"$(shell git -C \""$$_PRO_FILE_PWD_"\" rev-parse --verify HEAD 2>/dev/null || true)\\\""
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
# You can make your code warn on compile time for the TODO's
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += TODO_LIST
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
#ToDo comment close the gap with Cmake
|
||||
#this is my next problem now
|
||||
INCLUDEPATH += sources/ui
|
||||
|
||||
#comment close the gap with Cmake (De-Backer)
|
||||
#DEPENDPATH += .
|
||||
#INCLUDEPATH += sources \
|
||||
# sources/titleblock \
|
||||
# sources/ui \
|
||||
# sources/qetgraphicsitem \
|
||||
# sources/qetgraphicsitem/ViewItem \
|
||||
# sources/qetgraphicsitem/ViewItem/ui \
|
||||
# sources/richtext \
|
||||
# sources/factory \
|
||||
# sources/properties \
|
||||
# sources/dvevent \
|
||||
# sources/editor \
|
||||
# sources/editor/esevent \
|
||||
# sources/editor/graphicspart \
|
||||
# sources/editor/ui \
|
||||
# sources/editor/UndoCommand \
|
||||
# sources/undocommand \
|
||||
# sources/diagramevent \
|
||||
# sources/ElementsCollection \
|
||||
# sources/ElementsCollection/ui \
|
||||
# sources/autoNum \
|
||||
# sources/autoNum/ui \
|
||||
# sources/ui/configpage \
|
||||
# sources/SearchAndReplace \
|
||||
# sources/SearchAndReplace/ui \
|
||||
# sources/NameList \
|
||||
# sources/NameList/ui \
|
||||
# sources/utils \
|
||||
# pugixml \
|
||||
# sources/dataBase \
|
||||
# sources/dataBase/ui \
|
||||
# sources/factory/ui \
|
||||
# sources/print
|
||||
|
||||
# Fichiers sources
|
||||
HEADERS += $$files(sources/*.h) \
|
||||
$$files(sources/project/*.h) \
|
||||
$$files(sources/ui/*.h) \
|
||||
$$files(sources/editor/*.h) \
|
||||
$$files(sources/titleblock/*.h) \
|
||||
$$files(sources/richtext/*.h) \
|
||||
$$files(sources/qetgraphicsitem/*.h) \
|
||||
$$files(sources/qetgraphicsitem/ViewItem/*.h) \
|
||||
$$files(sources/qetgraphicsitem/ViewItem/ui/*.h) \
|
||||
$$files(sources/factory/*.h) \
|
||||
$$files(sources/properties/*.h) \
|
||||
$$files(sources/editor/ui/*.h) \
|
||||
$$files(sources/editor/esevent/*.h) \
|
||||
$$files(sources/editor/graphicspart/*.h) \
|
||||
$$files(sources/editor/UndoCommand/*h) \
|
||||
$$files(sources/dvevent/*.h) \
|
||||
$$files(sources/undocommand/*.h) \
|
||||
$$files(sources/diagramevent/*.h) \
|
||||
$$files(sources/ElementsCollection/*.h) \
|
||||
$$files(sources/ElementsCollection/ui/*.h) \
|
||||
$$files(sources/autoNum/*.h) \
|
||||
$$files(sources/autoNum/ui/*.h) \
|
||||
$$files(sources/ui/configpage/*.h) \
|
||||
$$files(sources/SearchAndReplace/*.h) \
|
||||
$$files(sources/SearchAndReplace/ui/*.h) \
|
||||
$$files(sources/NameList/*.h) \
|
||||
$$files(sources/NameList/ui/*.h) \
|
||||
$$files(sources/utils/*.h) \
|
||||
$$files(pugixml/src/*.hpp) \
|
||||
$$files(sources/dataBase/*.h) \
|
||||
$$files(sources/dataBase/ui/*.h) \
|
||||
$$files(sources/factory/ui/*.h) \
|
||||
$$files(sources/print/*.h) \
|
||||
$$files(sources/TerminalStrip/*.h) \
|
||||
$$files(sources/TerminalStrip/ui/*.h) \
|
||||
$$files(sources/TerminalStrip/ui/ConfigPage/*h) \
|
||||
$$files(sources/TerminalStrip/UndoCommand/*.h) \
|
||||
$$files(sources/TerminalStrip/GraphicsItem/*.h) \
|
||||
$$files(sources/TerminalStrip/GraphicsItem/properties/*.h) \
|
||||
$$files(sources/xml/*.h) \
|
||||
$$files(sources/dxf/*.h) \
|
||||
$$files(sources/qet_elementscaler/*.h) \
|
||||
$$files(sources/svg/*.h) \
|
||||
$$files(sources/import/edz/*.h) \
|
||||
$$files(sources/import/edz/lzma/*.h) \
|
||||
$$files(sources/logging/*.h) \
|
||||
$$files(sources/logging/ui/*.h)
|
||||
|
||||
SOURCES += $$files(sources/*.cpp) \
|
||||
$$files(sources/editor/*.cpp) \
|
||||
$$files(sources/project/*.cpp) \
|
||||
$$files(sources/titleblock/*.cpp) \
|
||||
$$files(sources/richtext/*.cpp) \
|
||||
$$files(sources/ui/*.cpp) \
|
||||
$$files(sources/qetgraphicsitem/*.cpp) \
|
||||
$$files(sources/qetgraphicsitem/ViewItem/*.cpp) \
|
||||
$$files(sources/qetgraphicsitem/ViewItem/ui/*.cpp) \
|
||||
$$files(sources/factory/*.cpp) \
|
||||
$$files(sources/properties/*.cpp) \
|
||||
$$files(sources/editor/ui/*.cpp) \
|
||||
$$files(sources/editor/esevent/*.cpp) \
|
||||
$$files(sources/editor/graphicspart/*.cpp) \
|
||||
$$files(sources/editor/UndoCommand/*cpp) \
|
||||
$$files(sources/dvevent/*.cpp) \
|
||||
$$files(sources/undocommand/*.cpp) \
|
||||
$$files(sources/diagramevent/*.cpp) \
|
||||
$$files(sources/ElementsCollection/*.cpp) \
|
||||
$$files(sources/ElementsCollection/ui/*.cpp) \
|
||||
$$files(sources/autoNum/*.cpp) \
|
||||
$$files(sources/autoNum/ui/*.cpp) \
|
||||
$$files(sources/ui/configpage/*.cpp) \
|
||||
$$files(sources/SearchAndReplace/*.cpp) \
|
||||
$$files(sources/SearchAndReplace/ui/*.cpp) \
|
||||
$$files(sources/NameList/*.cpp) \
|
||||
$$files(sources/NameList/ui/*.cpp) \
|
||||
$$files(sources/utils/*.cpp) \
|
||||
$$files(pugixml/src/*.cpp) \
|
||||
$$files(sources/dataBase/*.cpp) \
|
||||
$$files(sources/dataBase/ui/*.cpp) \
|
||||
$$files(sources/factory/ui/*.cpp) \
|
||||
$$files(sources/print/*.cpp) \
|
||||
$$files(sources/TerminalStrip/*.cpp) \
|
||||
$$files(sources/TerminalStrip/ui/*.cpp) \
|
||||
$$files(sources/TerminalStrip/ui/ConfigPage/*cpp) \
|
||||
$$files(sources/TerminalStrip/UndoCommand/*.cpp) \
|
||||
$$files(sources/TerminalStrip/GraphicsItem/*.cpp) \
|
||||
$$files(sources/TerminalStrip/GraphicsItem/properties/*.cpp) \
|
||||
$$files(sources/xml/*.cpp) \
|
||||
$$files(sources/dxf/*.cpp) \
|
||||
$$files(sources/qet_elementscaler/*.cpp) \
|
||||
$$files(sources/svg/*.cpp) \
|
||||
$$files(sources/import/edz/*.cpp) \
|
||||
$$files(sources/import/edz/lzma/*.c) \
|
||||
$$files(sources/logging/*.cpp) \
|
||||
$$files(sources/logging/ui/*.cpp)
|
||||
|
||||
|
||||
# Needed for use promote QTreeWidget in terminalstripeditor.ui
|
||||
INCLUDEPATH += sources/TerminalStrip/ui
|
||||
|
||||
# Needed for the EPLAN .edz importer (PR #513) and its bundled lzma/7z sources
|
||||
INCLUDEPATH += sources/import/edz
|
||||
INCLUDEPATH += sources/import/edz/lzma
|
||||
|
||||
# Liste des fichiers qui seront incorpores au binaire en tant que ressources Qt
|
||||
RESOURCES += qelectrotech.qrc
|
||||
|
||||
# Liste des ressources Windows
|
||||
#RC_FILE = ico/windows_icon/qelectrotech.rc
|
||||
|
||||
# Fichiers de traduction qui seront installes
|
||||
TRANSLATIONS += lang/*.ts
|
||||
|
||||
# Modules Qt utilises par l'application
|
||||
QT += xml svg network sql widgets printsupport concurrent gui-private
|
||||
|
||||
# KDE Frameworks 5 (KWidgetsAddons, KCoreAddons) are optional.
|
||||
#
|
||||
# Pass CONFIG+=no_kf5 to qmake to build against the Qt-only replacements in
|
||||
# sources/ui/nokde instead. This mirrors the CMake option BUILD_WITH_KF5=OFF
|
||||
# and is the easiest route on Windows/MinGW, where KF5 is awkward to obtain.
|
||||
#
|
||||
# qmake CONFIG+=no_kf5 qelectrotech.pro
|
||||
#
|
||||
# sources/ui/nokde is only added to the include path in that configuration, so
|
||||
# a normal KF5 build is unaffected.
|
||||
no_kf5 {
|
||||
DEFINES += BUILD_WITHOUT_KF5
|
||||
INCLUDEPATH += sources/ui/nokde
|
||||
HEADERS += $$files(sources/ui/nokde/*.h)
|
||||
SOURCES += $$files(sources/ui/nokde/*.cpp)
|
||||
} else {
|
||||
QT += KWidgetsAddons KCoreAddons
|
||||
}
|
||||
|
||||
# Private Qt GUI headers (needed for QPdfEngine::drawHyperlink)
|
||||
# gui-private should add this automatically, but some distros need it explicit
|
||||
INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtGui/$$[QT_VERSION]/QtGui
|
||||
|
||||
# UI DESIGNER FILES AND GENERATION SOURCES FILES
|
||||
FORMS += $$files(sources/richtext/*.ui) \
|
||||
$$files(sources/ui/*.ui) \
|
||||
$$files(sources/editor/ui/*.ui) \
|
||||
$$files(sources/ElementsCollection/ui/*.ui) \
|
||||
$$files(sources/autoNum/ui/*.ui) \
|
||||
$$files(sources/ui/configpage/*.ui) \
|
||||
$$files(sources/SearchAndReplace/ui/*.ui) \
|
||||
$$files(sources/NameList/ui/*.ui) \
|
||||
$$files(sources/qetgraphicsitem/ViewItem/ui/*.ui) \
|
||||
$$files(sources/dataBase/ui/*.ui) \
|
||||
$$files(sources/factory/ui/*.ui) \
|
||||
$$files(sources/print/*.ui) \
|
||||
$$files(sources/TerminalStrip/ui/*.ui) \
|
||||
$$files(sources/TerminalStrip/ui/ConfigPage/*.ui)
|
||||
|
||||
UI_SOURCES_DIR = sources/ui/
|
||||
UI_HEADERS_DIR = sources/ui/
|
||||
|
||||
# Configuration de la compilation
|
||||
CONFIG += c++17 debug_and_release warn_on link_pkgconfig
|
||||
|
||||
# Nom du binaire genere par la compilation
|
||||
TARGET = qelectrotech
|
||||
|
||||
# Ajustement des bibliotheques utilisees lors de l'edition des liens
|
||||
unix:QMAKE_LIBS_THREAD -= -lpthread
|
||||
unix|win32: PKGCONFIG += sqlite3
|
||||
|
||||
# Enable C++17
|
||||
QMAKE_CXXFLAGS += -std=c++17
|
||||
|
||||
# Description de l'installation
|
||||
target.path = $$join(INSTALL_PREFIX,,,$${QET_BINARY_PATH})
|
||||
|
||||
elements.path = $$join(INSTALL_PREFIX,,,$${QET_COMMON_COLLECTION_PATH})
|
||||
elements.files = elements/*
|
||||
|
||||
tbt.path = $$join(INSTALL_PREFIX,,,$${QET_COMMON_TBT_PATH})
|
||||
tbt.files = titleblocks/*
|
||||
|
||||
lang.path = $$join(INSTALL_PREFIX,,,$${QET_LANG_PATH})
|
||||
lang.files = $$replace(TRANSLATIONS, '.ts', '.qm')
|
||||
|
||||
examples.path = $$join(INSTALL_PREFIX,,,$${QET_EXAMPLES_PATH})
|
||||
examples.files = examples/*
|
||||
|
||||
copyright.path = $$join(INSTALL_PREFIX,,,$${QET_LICENSE_PATH})
|
||||
copyright.files = LICENSE ELEMENTS.LICENSE CREDIT README ChangeLog
|
||||
|
||||
mime_package.path = $$join(INSTALL_PREFIX,,,$${QET_MIME_PACKAGE_PATH})
|
||||
mime_package.files = misc/qelectrotech.xml
|
||||
|
||||
desktop.path = $$join(INSTALL_PREFIX,,,$${QET_DESKTOP_PATH})
|
||||
desktop.files = misc/org.qelectrotech.qelectrotech.desktop
|
||||
|
||||
appdata.path = $$join(INSTALL_PREFIX,,,$${QET_APPDATA_PATH})
|
||||
appdata.files = misc/qelectrotech.appdata.xml
|
||||
|
||||
icons.path = $$join(INSTALL_PREFIX,,,$${QET_ICONS_PATH})
|
||||
icons.files = ico/breeze-icons/16x16 \
|
||||
ico/breeze-icons/22x22 \
|
||||
ico/breeze-icons/32x32 \
|
||||
ico/breeze-icons/48x48 \
|
||||
ico/breeze-icons/64x64 \
|
||||
ico/breeze-icons/128x128 \
|
||||
ico/breeze-icons/256x256
|
||||
|
||||
man.path = $$join(INSTALL_PREFIX,,,$${QET_MAN_PATH})
|
||||
man.files = man/files/*
|
||||
man.extra = sh man/compress_man_pages.sh
|
||||
|
||||
# L'installation comprend la copie du binaire, des elements, des fichiers de langue et du fichier LICENSE
|
||||
INSTALLS += target elements tbt lang copyright
|
||||
# Sous Unix, on installe egalement l'icone, un fichier .desktop, des fichiers mime et les pages de manuel
|
||||
unix {
|
||||
INSTALLS += desktop mime_package icons man examples appdata
|
||||
}
|
||||
|
||||
# Options de compilation communes a Unix et MacOS X
|
||||
unix {
|
||||
# Chemin des fichiers de traduction ; par defaut : lang/ dans le repertoire d'execution
|
||||
DEFINES += QET_LANG_PATH=$$join(COMPIL_PREFIX,,,$${QET_LANG_PATH})
|
||||
|
||||
# Chemin de la collection commune ; par defaut : elements/ dans le repertoire d'execution
|
||||
DEFINES += QET_COMMON_COLLECTION_PATH=$$join(COMPIL_PREFIX,,,$${QET_COMMON_COLLECTION_PATH})
|
||||
|
||||
DEFINES += QET_COMMON_TBT_PATH=$$join(COMPIL_PREFIX,,,$${QET_COMMON_TBT_PATH})
|
||||
}
|
||||
|
||||
# Options de compilation specifiques a MacOS X
|
||||
macx {
|
||||
# les chemins definis precedemment sont relatifs au dossier contenant le binaire executable
|
||||
DEFINES += QET_LANG_PATH_RELATIVE_TO_BINARY_PATH
|
||||
DEFINES += QET_COMMON_COLLECTION_PATH_RELATIVE_TO_BINARY_PATH
|
||||
|
||||
|
||||
equals(QMAKE_TARGET.arch, x86) {
|
||||
message( "It's x86" )
|
||||
LIBS += /opt/digikam.org.x86_64/lib/libsqlite3.0.dylib
|
||||
}
|
||||
equals(QMAKE_TARGET.arch, arm64) {
|
||||
message( "It's arm64" )
|
||||
LIBS += /opt/digikam.org.arm64/lib/libsqlite3.0.dylib
|
||||
}
|
||||
}
|
||||
|
||||
# Compilers-specific options
|
||||
unix {
|
||||
QMAKE_COPY_DIR = 'cp -f -r --preserve=timestamps'
|
||||
}
|
||||
@@ -778,30 +778,6 @@ bool ElementsLocation::setXml(const QDomDocument &xml_document) const
|
||||
//Element doesn't exist, we create the element
|
||||
else
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
||||
QString path_ = collectionPath(false);
|
||||
QRegExp rx ("^(.*)/(.*\\.elmt)$");
|
||||
|
||||
if (rx.exactMatch(path_)) {
|
||||
return project()
|
||||
->embeddedElementCollection()
|
||||
->addElementDefinition(
|
||||
rx.cap(1),
|
||||
rx.cap(2),
|
||||
xml_document
|
||||
.documentElement());
|
||||
}
|
||||
else {
|
||||
qDebug() << "ElementsLocation::setXml :"
|
||||
" rx don't match";
|
||||
}
|
||||
#else
|
||||
#if TODO_LIST
|
||||
#pragma message("@TODO remove code for QT 6 or later")
|
||||
# pragma message("@TODO ad Core5Compat to Cmake")
|
||||
#endif
|
||||
qDebug() << "Help code for QT 6 or later";
|
||||
|
||||
QString path_ = collectionPath(false);
|
||||
QRegularExpression rx("^(.*)/(.*\\.elmt)$");
|
||||
QRegularExpressionMatch match = rx.match(path_);
|
||||
@@ -820,7 +796,6 @@ bool ElementsLocation::setXml(const QDomDocument &xml_document) const
|
||||
qDebug() << "ElementsLocation::setXml :"
|
||||
" rx don't match";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ TerminalStripLayoutEditor::TerminalStripLayoutEditor(QSharedPointer<TerminalStri
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->m_graphics_view->setScene(new QGraphicsScene{ this });
|
||||
// The preview is printed output: black ink on a white page, whatever
|
||||
// the application palette.
|
||||
ui->m_graphics_view->setBackgroundBrush(Qt::white);
|
||||
ui->m_graphics_view->scene()->addItem(&m_preview_strip_item);
|
||||
updateUi();
|
||||
}
|
||||
|
||||
@@ -29,15 +29,9 @@
|
||||
#include "modelTerminalData.h"
|
||||
|
||||
//Code to use QColor as key for QHash
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
inline size_t qHash(const QColor &key, size_t seed = 0) {
|
||||
return qHash(key.rgba(), seed);
|
||||
}
|
||||
#else
|
||||
inline uint qHash(const QColor &key, uint seed) {
|
||||
return qHash(key.rgba(), seed);
|
||||
}
|
||||
#endif
|
||||
|
||||
//needed to use QPointer<Element> as key of QHash
|
||||
inline uint qHash(const QPointer<Element> &key, uint seed) {
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "../qetgraphicsitem/element.h"
|
||||
#include "../qetxml.h"
|
||||
#include "../qetproject.h"
|
||||
#include <QDir>
|
||||
#include <QDomDocument>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
#include <utility>
|
||||
@@ -703,6 +705,74 @@ namespace autonum
|
||||
return formula;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief prefixFromLabelFile
|
||||
Look up a prefix for @a path (path[dirLevel] outermost, path[1] the
|
||||
deepest directory; path[0], the element's own file name, is never
|
||||
matched) in the qet_labels.xml at @a filepath.
|
||||
|
||||
Descends through nested \<category name="..."\> elements matching
|
||||
path[dirLevel], path[dirLevel-1], ..., path[1] in turn, considering
|
||||
only *direct* children at each step -- unlike a flat token scan,
|
||||
this cannot be fooled by a same-named category living elsewhere in
|
||||
the document at the wrong nesting depth (bugtracker #671 item 5).
|
||||
|
||||
At each matched level, that category's own \<prefix\> child -- even
|
||||
an empty one -- overrides whatever a shallower ancestor already
|
||||
provided, so an explicit empty \<prefix/\> cancels inheritance
|
||||
rather than silently falling back to it (the behaviour requested in
|
||||
PR #686 review). A category with no \<prefix\> child at all leaves
|
||||
the inherited value untouched, which is how a directory with no
|
||||
prefix of its own comes to inherit its parent's, as the file's own
|
||||
header comment documents.
|
||||
|
||||
@return the prefix that applies, or a null QString if the file
|
||||
cannot be read, is not well-formed, or does not describe this
|
||||
path at all (as opposed to describing it with no prefix
|
||||
anywhere along it, which is a non-null empty string).
|
||||
*/
|
||||
static QString prefixFromLabelFile(const QString &filepath, const QStringList &path, int dirLevel)
|
||||
{
|
||||
QFile file(filepath);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return QString();
|
||||
|
||||
QDomDocument document;
|
||||
if (!document.setContent(&file))
|
||||
return QString();
|
||||
|
||||
QDomElement node = document.documentElement();
|
||||
if (node.isNull())
|
||||
return QString();
|
||||
|
||||
QString prefix;
|
||||
for (int i = dirLevel ; i >= 1 ; --i) {
|
||||
QDomElement child = node.firstChildElement(QStringLiteral("category"));
|
||||
while (!child.isNull()
|
||||
&& child.attribute(QStringLiteral("name")) != path[i]) {
|
||||
child = child.nextSiblingElement(QStringLiteral("category"));
|
||||
}
|
||||
if (child.isNull())
|
||||
return QString();
|
||||
node = child;
|
||||
|
||||
const QDomElement own = node.firstChildElement(QStringLiteral("prefix"));
|
||||
if (!own.isNull()) {
|
||||
//readElementText()'s null-vs-empty distinction that PR
|
||||
//#686 needed for the old QXmlStreamReader-based lookup
|
||||
//has a QDomElement equivalent: text() on an empty
|
||||
//element can itself come back null depending on how the
|
||||
//XML was written, so the same explicit fallback applies
|
||||
//-- an empty QString here means "found, deliberately
|
||||
//blank", not "not found".
|
||||
prefix = own.text();
|
||||
if (prefix.isNull())
|
||||
prefix = QString("");
|
||||
}
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief elementPrefixForLocation
|
||||
@param location
|
||||
@@ -716,114 +786,85 @@ namespace autonum
|
||||
if (!location.isProject())
|
||||
return QString();
|
||||
|
||||
QXmlStreamReader rxml;
|
||||
QString path[10];
|
||||
int i = -1;
|
||||
//Directory names from the element up to (not including) the
|
||||
//collection root, outermost last -- path[dirLevel] is the
|
||||
//top-level category, path[1] the element's immediate parent
|
||||
//directory, path[0] the element's own file name (never matched
|
||||
//against a category: the search stops descending once it has
|
||||
//matched path[1], the deepest real directory). An unbounded
|
||||
//QStringList rather than a fixed-size array, because a custom
|
||||
//collection can nest deeper than the shipped one -- see
|
||||
//bugtracker #671 item 3.
|
||||
QStringList path;
|
||||
ElementsLocation current_location = location;
|
||||
int dirLevel = -1;
|
||||
|
||||
//Add location name to path array
|
||||
while((current_location.parent() != current_location) && (current_location.parent().fileName() != "import"))
|
||||
while ((current_location.parent() != current_location)
|
||||
&& (current_location.parent().fileName() != "import"))
|
||||
{
|
||||
i++;
|
||||
path[i]=current_location.fileName();
|
||||
path << current_location.fileName();
|
||||
current_location = current_location.parent();
|
||||
dirLevel++;
|
||||
}
|
||||
//User Element without folder treatment
|
||||
if (i == -1)
|
||||
{
|
||||
i = 0;
|
||||
path[i]=current_location.fileName();
|
||||
//User element without folder treatment
|
||||
if (path.isEmpty()) {
|
||||
path << current_location.fileName();
|
||||
current_location = current_location.parent();
|
||||
dirLevel = 0;
|
||||
}
|
||||
const int dirLevel = path.size() - 1;
|
||||
//Name of the top-level tree the element's path was found
|
||||
//under, e.g. "10_electric" -- or, for a custom/company
|
||||
//collection not organised that way, whatever its top-level
|
||||
//folder happens to be called.
|
||||
const QString collection_root = current_location.fileName();
|
||||
|
||||
//Every top-level common-collection tree (10_electric,
|
||||
//20_logic, 30_hydraulic, ...) may carry its own
|
||||
//qet_labels.xml, with categories relative to that tree, the
|
||||
//same way 10_electric/qet_labels.xml already does -- not just
|
||||
//10_electric, which is all the hardcoded check this replaces
|
||||
//used to allow (bugtracker #671 item 2). commonElementsDir()
|
||||
//-- unlike customElementsDir(), which normalises this itself
|
||||
//-- returns whatever path the user configured verbatim, with
|
||||
//no guaranteed trailing separator; concatenating a suffix onto
|
||||
//it directly used to silently mangle the path (and so the
|
||||
//prefix lookup) for any install relocated to a directory
|
||||
//without a trailing slash (#671 item 1). QDir::filePath()
|
||||
//joins correctly either way.
|
||||
{
|
||||
const QString common_file = QDir(QETApp::commonElementsDir())
|
||||
.filePath(collection_root + QStringLiteral("/qet_labels.xml"));
|
||||
const QString prefix = prefixFromLabelFile(common_file, path, dirLevel);
|
||||
if (!prefix.isNull()) {
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
||||
// Create Custom labels if qet_labels.xml exits in customElementsDir
|
||||
if (current_location.fileName() != "10_electric"){
|
||||
QString custom_labels = "qet_labels.xml";
|
||||
QString customfilepath = QETApp::customElementsDir().append(custom_labels);
|
||||
/* Which collection an element actually came from is not
|
||||
* recoverable post-import (addElement() strips the protocol),
|
||||
* so custom and company labels files are tried against two
|
||||
* possible layouts: with the collection's top-level tree name
|
||||
* folded into the path (a custom/company file organised as a
|
||||
* mirror of the common collection, tree name included) and
|
||||
* without it (a file scoped to just this one tree, matching
|
||||
* how the common collection's own files are written). Custom
|
||||
* is tried before company, so a user override wins over a
|
||||
* shared one.
|
||||
*/
|
||||
QStringList path_from_root = path;
|
||||
path_from_root << collection_root;
|
||||
|
||||
QFile file(customfilepath);
|
||||
file.isReadable();
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return QString();
|
||||
rxml.setDevice(&file);
|
||||
rxml.readNext();
|
||||
|
||||
while(!rxml.atEnd())
|
||||
{
|
||||
if (rxml.attributes().value("name").toString() == path[i])
|
||||
{
|
||||
rxml.readNext();
|
||||
i=i-1;
|
||||
//reached element directory
|
||||
if (i==0)
|
||||
{
|
||||
for (int j=i; j<= dirLevel; j = j +1)
|
||||
{
|
||||
//if there is a prefix available apply prefix
|
||||
if(rxml.name().toString()=="prefix")
|
||||
{
|
||||
return rxml.readElementText();
|
||||
}
|
||||
//if there isn't a prefix available, find parent prefix in parent folder
|
||||
else
|
||||
{
|
||||
while (rxml.readNextStartElement() && rxml.name().toString()!="prefix")
|
||||
{
|
||||
rxml.skipCurrentElement();
|
||||
rxml.readNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
const QStringList candidate_dirs = {
|
||||
QETApp::customElementsDir(),
|
||||
QETApp::companyElementsDir()
|
||||
};
|
||||
for (const QString &dir : candidate_dirs) {
|
||||
const QString candidate =
|
||||
QDir(dir).filePath(QStringLiteral("qet_labels.xml"));
|
||||
for (const QStringList &segments : {path_from_root, path}) {
|
||||
const QString prefix = prefixFromLabelFile(
|
||||
candidate, segments, segments.size() - 1);
|
||||
if (!prefix.isNull()) {
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
rxml.readNext();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString qet_labels = "10_electric/qet_labels.xml";
|
||||
QString filepath = QETApp::commonElementsDir().append(qet_labels);
|
||||
QFile file(filepath);
|
||||
file.isReadable();
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return QString();
|
||||
|
||||
rxml.setDevice(&file);
|
||||
rxml.readNext();
|
||||
|
||||
while(!rxml.atEnd())
|
||||
{
|
||||
if (rxml.attributes().value("name").toString() == path[i])
|
||||
{
|
||||
rxml.readNext();
|
||||
i=i-1;
|
||||
//reached element directory
|
||||
if (i==0)
|
||||
{
|
||||
for (int j=i; j<= dirLevel; j = j +1)
|
||||
{
|
||||
//if there is a prefix available apply prefix
|
||||
if(rxml.name().toString()=="prefix")
|
||||
{
|
||||
return rxml.readElementText();
|
||||
}
|
||||
//if there isn't a prefix available, find parent prefix in parent folder
|
||||
else
|
||||
{
|
||||
while (rxml.readNextStartElement() && rxml.name().toString()!="prefix")
|
||||
{
|
||||
rxml.skipCurrentElement();
|
||||
rxml.readNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rxml.readNext();
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ FolioAutonumberingW::~FolioAutonumberingW()
|
||||
*/
|
||||
void FolioAutonumberingW::setContext(QList <QString> autonums)
|
||||
{
|
||||
// Replace the list rather than append to it: this is called again
|
||||
// whenever the project's numberings change (import, for instance),
|
||||
// and appending gave a second copy of every name.
|
||||
ui->m_autonums_cb->clear();
|
||||
foreach (QString str, autonums) { ui->m_autonums_cb->addItem(str);}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "bomexport.h"
|
||||
|
||||
#include <QSaveFile>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlRecord>
|
||||
#include <QVariant>
|
||||
|
||||
namespace {
|
||||
QString csvField(QString value)
|
||||
{
|
||||
value.replace(QLatin1Char('"'), QStringLiteral("\"\""));
|
||||
return QLatin1Char('"') + value + QLatin1Char('"');
|
||||
}
|
||||
|
||||
QByteArray csvRecord(const QStringList &values)
|
||||
{
|
||||
QStringList escaped;
|
||||
for (const auto &value : values) {
|
||||
escaped.append(csvField(value));
|
||||
}
|
||||
return (escaped.join(QLatin1Char(';')) + QLatin1Char('\n')).toUtf8();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList BomExport::defaultColumns()
|
||||
{
|
||||
return {
|
||||
QStringLiteral("label"),
|
||||
QStringLiteral("designation"),
|
||||
QStringLiteral("manufacturer"),
|
||||
QStringLiteral("manufacturer_reference"),
|
||||
QStringLiteral("model"),
|
||||
QStringLiteral("description"),
|
||||
QStringLiteral("category"),
|
||||
QStringLiteral("quantity"),
|
||||
QStringLiteral("voltage_rating"),
|
||||
QStringLiteral("current_rating"),
|
||||
QStringLiteral("folio"),
|
||||
QStringLiteral("notes")
|
||||
};
|
||||
}
|
||||
|
||||
QString BomExport::defaultQuery()
|
||||
{
|
||||
//Slaves and terminals are included because both are routinely
|
||||
//separately orderable hardware. A circuit breaker can carry ten or
|
||||
//twenty auxiliary blocks, each with its own order code, and a
|
||||
//terminal block is a purchased part in its own right. Neither shares
|
||||
//a line with its master: the query is ungrouped, one row per element,
|
||||
//so each appears as the distinct item it is.
|
||||
//
|
||||
//Anything that should not be ordered is kept out by setting
|
||||
//exclude_from_bom on the element, which the view already honours --
|
||||
//a relay's own auxiliary contact, say.
|
||||
//
|
||||
//Thumbnails are deliberately left out for now even though ten of
|
||||
//them in the shipped examples carry manufacturer and reference data
|
||||
//(the assembly-plan mounting-plate symbols), because that has not
|
||||
//been asked for and is a separate question. The folio report arrows
|
||||
//and the conductor definition stay out because they are not hardware.
|
||||
//
|
||||
//See discussion #847.
|
||||
return QStringLiteral("SELECT %1 FROM element_nomenclature_view "
|
||||
"WHERE element_type IN "
|
||||
"('simple', 'master', 'slave', 'terminal') "
|
||||
"ORDER BY diagram_position, position, label")
|
||||
.arg(defaultColumns().join(QStringLiteral(", ")));
|
||||
}
|
||||
|
||||
QByteArray BomExport::toCsv(QSqlQuery &query, const QStringList &headers,
|
||||
bool include_headers, int *row_count)
|
||||
{
|
||||
QByteArray csv("\xEF\xBB\xBF");
|
||||
if (include_headers) {
|
||||
csv += csvRecord(headers);
|
||||
}
|
||||
int rows = 0;
|
||||
while (query.next())
|
||||
{
|
||||
QStringList values;
|
||||
for (int i = 0; i < query.record().count(); ++i) {
|
||||
values.append(query.value(i).toString());
|
||||
}
|
||||
csv += csvRecord(values);
|
||||
++rows;
|
||||
}
|
||||
if (row_count) {
|
||||
*row_count = rows;
|
||||
}
|
||||
return csv;
|
||||
}
|
||||
|
||||
bool BomExport::writeCsv(const QString &file_path, const QByteArray &csv,
|
||||
QString *error)
|
||||
{
|
||||
if (error) {
|
||||
error->clear();
|
||||
}
|
||||
QSaveFile file(file_path);
|
||||
if (!file.open(QIODevice::WriteOnly) || file.write(csv) != csv.size())
|
||||
{
|
||||
if (error) {
|
||||
*error = file.errorString();
|
||||
}
|
||||
file.cancelWriting();
|
||||
return false;
|
||||
}
|
||||
if (!file.commit())
|
||||
{
|
||||
if (error) {
|
||||
*error = file.errorString();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2006-2026 The QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
QElectroTech 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef BOMEXPORT_H
|
||||
#define BOMEXPORT_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
class QSqlQuery;
|
||||
|
||||
namespace BomExport
|
||||
{
|
||||
QStringList defaultColumns();
|
||||
QString defaultQuery();
|
||||
QByteArray toCsv(QSqlQuery &query, const QStringList &headers,
|
||||
bool include_headers = true, int *row_count = nullptr);
|
||||
bool writeCsv(const QString &file_path, const QByteArray &csv,
|
||||
QString *error = nullptr);
|
||||
}
|
||||
|
||||
#endif // BOMEXPORT_H
|
||||
@@ -55,12 +55,6 @@ BorderTitleBlock::BorderTitleBlock(QObject *parent) :
|
||||
m_titleblock_template_renderer = new TitleBlockTemplateRenderer(this);
|
||||
m_titleblock_template_renderer -> setTitleBlockTemplate(QETApp::defaultTitleBlockTemplate());
|
||||
|
||||
// disable the QPicture-based cache from Qt 4.8 to avoid rendering errors and crashes
|
||||
#if QT_VERSION < QT_VERSION_CHECK(4, 8, 0) // ### Qt 6: remove
|
||||
#else
|
||||
m_titleblock_template_renderer -> setUseCache(false);
|
||||
#endif
|
||||
|
||||
// dimensions par defaut du schema
|
||||
importBorder(BorderProperties());
|
||||
|
||||
@@ -410,12 +404,10 @@ QString BorderTitleBlock::titleBlockTemplateName() const
|
||||
@brief BorderTitleBlock::titleBlockTemplateChanged
|
||||
This slot may be used to inform this class that the given title block
|
||||
template has changed.
|
||||
The title block-dedicated rendering cache will thus be flushed.
|
||||
@param template_name : Name of the title block template that has changed
|
||||
*/
|
||||
void BorderTitleBlock::titleBlockTemplateChanged(const QString &template_name) {
|
||||
if (titleBlockTemplateName() != template_name) return;
|
||||
m_titleblock_template_renderer -> invalidateRenderedTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user