Compare commits

..

96 Commits

Author SHA1 Message Date
Laurent Trinques bbf156c489 Merge pull request #455 from Kellermorph/makro-fix
Auto-build doxygen docs / doxygen (push) Failing after 2m38s
Auto-build doxygen docs / deploy (push) Has been skipped
Fix Thumbnail in Makrotree
2026-04-29 17:37:19 +02:00
Kellermorph 946aa37e78 delete german notes 2026-04-29 16:17:49 +02:00
Kellermorph b8c85f9e96 Fix placing Template 2026-04-29 16:15:58 +02:00
Kellermorph ee8114d42c Fix Thumbnail in Makrotree 2026-04-29 15:56:00 +02:00
Laurent Trinques 0abfecd891 Merge pull request #454 from Kellermorph/update-translation-de
Auto-build doxygen docs / doxygen (push) Failing after 2m43s
Auto-build doxygen docs / deploy (push) Has been skipped
Update German translation for macro feature
2026-04-28 06:19:10 +02:00
Kellermorph a434575857 Update German translation for macro feature 2026-04-27 20:43:20 +02:00
Laurent Trinques fc7d8f5f6f Merge pull request #451 from Kellermorph/makro
Auto-build doxygen docs / doxygen (push) Failing after 2m31s
Auto-build doxygen docs / deploy (push) Has been skipped
Draft: Feature - Introduce User Templates Collection and Dedicated UI Tab
2026-04-26 14:10:07 +02:00
Kellermorph 1d451a6490 Fix include paths for NameList header 2026-04-26 13:01:19 +02:00
Kellermorph 0118d94d4e makro 2026-04-26 10:48:47 +02:00
Laurent Trinques b80875c583 Fix typo in previous commit
Auto-build doxygen docs / doxygen (push) Failing after 2m30s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-25 12:54:52 +02:00
Laurent Trinques b54327e649 Revert "Update translation missing in qelectrotech_appdata.xml, electrotech.xml, org_qelectrotech_qelectrotech.desktop"
This reverts commit e046b8289d.
2026-04-25 12:52:39 +02:00
Laurent Trinques e046b8289d Update translation missing in qelectrotech_appdata.xml, electrotech.xml, org_qelectrotech_qelectrotech.desktop 2026-04-25 12:42:39 +02:00
Laurent Trinques 941efe6405 Typo 2026-04-25 12:05:29 +02:00
Laurent Trinques 07e11ea659 Try to fix NSIS : LangString "Fonts" is not set in language table of language * 2026-04-25 12:01:06 +02:00
Laurent Trinques 387f96b556 Update packaging_script_Debian_Ubuntu_Windows.sh 2026-04-25 11:29:48 +02:00
Laurent Trinques 0832ef47a8 NSIS add Fonts directory on Windows installer 2026-04-25 11:17:48 +02:00
Laurent Trinques bc7f852f79 Add Missing language translations for QElectroTech installer
Auto-build doxygen docs / doxygen (push) Failing after 1m10s
Auto-build doxygen docs / deploy (push) Has been skipped
Languages added: hu, ja, mn, nb, nl_BE, nl_NL, pt_BR, rs/sr, sk, sl, sv, tr, uk, zh
2026-04-24 13:29:39 +02:00
Laurent Trinques d1e10afd61 Add notes.md
Auto-build doxygen docs / doxygen (push) Failing after 2m34s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-24 13:05:27 +02:00
Laurent Trinques 8aa384d305 NSIS: remove LANG_DUTCH_BELGIAN
Auto-build doxygen docs / doxygen (push) Failing after 1m11s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-23 14:40:35 +02:00
Laurent Trinques b321460116 NSIS, tRy to add LANG_DUTCH_BELGIAN, improve others not translated strings 2026-04-23 14:18:57 +02:00
Laurent Trinques 416ec501fe GenerateSvg: Corrected view:
Auto-build doxygen docs / doxygen (push) Failing after 2m28s
Auto-build doxygen docs / deploy (push) Has been skipped
The contents of svg export is not correctly centered within the exported
area, thanks Tom
https://qelectrotech.org/forum/viewtopic.php?pid=22781#p22781
2026-04-23 09:49:42 +02:00
Laurent Trinques 145810f33a Update Windows installer NSIS to 3.X version 2026-04-23 09:31:46 +02:00
Laurent Trinques 4f70468a29 Merge pull request #452 from ChuckNr11/master
Auto-build doxygen docs / doxygen (push) Failing after 2m29s
Auto-build doxygen docs / deploy (push) Has been skipped
Fix losing Focus on moving diagram position with keyboard
2026-04-19 14:32:37 +02:00
ChuckNr11 f60acad3b3 Fix losing Focus on moving diagram position with keyboard
Due to the changes made in the commit "Add highlight current page in
ProjectView", there is a problem when moving diagrams in the ProjectView
using the keyboard. The diagrams lose focus after being moved.
The cause is: The DiagramItem loses its selection before the move
function is executed.

The code has been adjusted.
2026-04-19 10:44:52 +02:00
Kellermorph ee65142b65 makro 2026-04-16 12:47:02 +02:00
Laurent Trinques 03bb97b529 Add DE binary translation *qm file.
Auto-build doxygen docs / doxygen (push) Failing after 1m9s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-15 17:06:29 +02:00
Laurent Trinques a4b90f3cc7 Merge pull request #450 from Kellermorph/master
Auto-build doxygen docs / doxygen (push) Failing after 2m29s
Auto-build doxygen docs / deploy (push) Has been skipped
Update translation
2026-04-15 06:20:24 +02:00
Kellermorph d57a219977 Merge branch 'master' into master 2026-04-14 21:54:01 +02:00
Kellermorph 03afa9e318 Update translation 2026-04-14 21:49:05 +02:00
Laurent Trinques 37cec4afce Fix french translations
Auto-build doxygen docs / doxygen (push) Failing after 2m21s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-12 12:46:15 +02:00
Laurent Trinques 12f04a7b08 Update translation files *TS
Auto-build doxygen docs / doxygen (push) Failing after 1m6s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-09 18:56:24 +02:00
Laurent Trinques ba77b3dabb Update qelectrotech.appdata.xml 2026-04-09 17:13:18 +02:00
Laurent Trinques 2e6953bbd0 Update org.qelectrotech.qelectrotech.desktop 2026-04-09 17:05:26 +02:00
Laurent Trinques c4e05f817c Merge pull request #449 from Kellermorph/feature-terminal-numbering
Auto-build doxygen docs / doxygen (push) Failing after 1m40s
Auto-build doxygen docs / deploy (push) Has been skipped
Automatic Terminal Numbering Tool
2026-04-09 13:02:40 +02:00
Kellermorph eb8f859038 Terminal numbering 2026-04-09 08:36:54 +02:00
Laurent Trinques 16650ed6af Update org.qelectrotech.QElectroTech.json
Auto-build doxygen docs / doxygen (push) Failing after 38s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-06 10:19:26 +02:00
Laurent Trinques 3b3171dc93 Update org.qelectrotech.QElectroTech.json 2026-04-06 09:18:39 +02:00
Laurent Trinques 500c42c86b Delete build-aux/flatpak/patches/0001-build-Fix-the-installation-paths.patch 2026-04-06 08:41:56 +02:00
Laurent Trinques 2f3e46e488 Add files via upload 2026-04-06 08:41:27 +02:00
Laurent Trinques 290ef97ec2 Delete build-aux/flatpak/fix-appdata.patch 2026-04-06 08:37:15 +02:00
Laurent Trinques f0923e7560 Delete build-aux/flatpak/tkinter-build.patch 2026-04-06 08:36:57 +02:00
Laurent Trinques b32de35afd Add files via upload 2026-04-06 08:34:20 +02:00
Laurent Trinques 8aad1c0cab Update org.qelectrotech.QElectroTech.json 2026-04-06 08:31:42 +02:00
Laurent Trinques d365e19619 Update org.qelectrotech.QElectroTech.json 2026-04-06 06:55:18 +02:00
Laurent Trinques 27b977e9f3 Update translation TS files 2026-04-06 06:12:01 +02:00
Laurent Trinques 54e19f4074 Merge pull request #448 from ChuckNr11/master
Supplement to pull request #444 by Kellermorph
2026-04-06 05:50:03 +02:00
Laurent Trinques 8af1fd708f Merge pull request #447 from Kellermorph/feature-verdrahtungsplan
Add RAM-based wiring list export
2026-04-06 05:47:24 +02:00
ChuckNr11 a64e414d63 Fix: incorrect display after deleting a diagram in elements panel 2026-04-05 22:44:35 +02:00
ChuckNr11 2ed8d76e2d add buttons 'one page left/right' to projectView tab bar
Disable the QTabWidget internal scroll buttons and add own buttons for
scroll 'one page left' and scroll 'one page right'. The scrolled
diagrams will be activated.
2026-04-05 22:39:53 +02:00
ChuckNr11 679647f52a Change operation of elementsPanel
corresponding to operation of project and diagram tabs
- click on the item activates the corresponding diagram or project.
- double click opens the corresponding properties editor.
- selecting with the up and down arrow keys has the same effect.
2026-04-05 22:21:34 +02:00
ChuckNr11 a82f6de23b Add highlight current page in ProjectView
- on clicking project tab
- on moving diagram tab
- on adding project
- on adding diagram
2026-04-05 22:11:38 +02:00
ChuckNr11 6452e03cdc refactor: move code to other place for cleaner code
connections for projectviews are made in "addProjectView"
2026-04-05 21:56:33 +02:00
Kellermorph 51725d9d8e Replace conductornumexport.cpp with wiringlistexport.h 2026-04-05 18:32:35 +02:00
Kellermorph a45a7d4e4d Remove comments about live RAM capture
Removed commented-out code explaining live RAM capture.
2026-04-05 09:09:51 +02:00
Kellermorph bc9173d726 Add RAM-based wiring list export 2026-04-05 08:33:37 +02:00
Laurent Trinques 19712d72ef TYpo
Auto-build doxygen docs / doxygen (push) Failing after 35s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-03 14:14:29 +02:00
Laurent Trinques f23ec620dc Typo
Auto-build doxygen docs / doxygen (push) Failing after 35s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-02 20:51:19 +02:00
Laurent Trinques 47d2107d99 Update translation file *.TS
Auto-build doxygen docs / doxygen (push) Failing after 35s
Auto-build doxygen docs / deploy (push) Has been skipped
2026-04-02 17:15:19 +02:00
Laurent Trinques 0a4c3f4601 Improve comment! 2026-04-02 17:05:06 +02:00
Laurent Trinques ab24b74c72 Now, elementproperties widget: add MAX contact slave, and count slave
contacts linked to this master, show these informations only when
element type is master.
2026-04-02 15:46:56 +02:00
Laurent Trinques 380d12e675 Typo 2026-04-02 15:35:04 +02:00
Laurent Trinques d0d3194afa On elementpropertieswidget add MAX conctact slave contact and count
slave contacts linked to this master
2026-04-02 15:07:50 +02:00
Laurent Trinques b18f5f5e41 Update translation file *.TS 2026-04-02 12:01:38 +02:00
Laurent Trinques 8a1b0575ab git submodule update --remote elements 2026-04-02 11:49:06 +02:00
Laurent Trinques 67ec648706 Merge pull request #444 from Kellermorph/master
Follow-up: Address review comments for slave limit feature
2026-04-02 11:47:21 +02:00
Kellermorph 9b77b4d4fa Update rectangle height and add QLabel for hidden masters 2026-04-01 16:51:41 +02:00
Kellermorph 225edec091 Translate warning message to French 2026-03-31 20:33:44 +02:00
Kellermorph 62dbaddab2 Update checkbox text for max slaves setting 2026-03-31 20:21:03 +02:00
Kellermorph f5857bb1fd Update comment for clarity in element properties editor 2026-03-31 20:15:35 +02:00
Kellermorph 825eeb77e4 Translate comments to English and clarify filtering logic 2026-03-31 20:14:51 +02:00
Kellermorph 780cf8b054 Set default text color for slave Xref item 2026-03-31 19:57:45 +02:00
Kellermorph 605392cf9b Filter out full MasterElements from elmt_vector
Added filtering for full MasterElements from the list of elements.
2026-03-31 17:53:01 +02:00
Kellermorph 3795ddb1f5 Refactor context menu and link button logic 2026-03-31 17:52:26 +02:00
Kellermorph ecee2209e6 Add isFull method to check Slave-Limit 2026-03-31 17:51:53 +02:00
Kellermorph 246dd0a42f Refactor MasterElement::isFull for clarity 2026-03-31 17:51:32 +02:00
Kellermorph 89a4aaac28 Refactor conditional checks for Master type 2026-03-31 17:50:46 +02:00
Kellermorph 79edc3fbb7 Clean up whitespace in elementdata.h
Removed unnecessary blank lines in elementdata.h
2026-03-31 17:50:22 +02:00
Kellermorph 52f61ab500 Refactor max_slaves handling in ElementPropertiesEditor 2026-03-31 17:49:21 +02:00
Kellermorph 1bbb374094 Update height and add max slaves options in UI 2026-03-31 17:47:45 +02:00
Laurent Trinques c220d84fcb Update elementdata.h 2026-03-31 16:23:05 +02:00
Kellermorph 4834d41432 Merge branch 'master' into master 2026-03-31 14:14:02 +02:00
Kellermorph 378aa8899f Remove resizing of first column in properties editor
Removed resizing of the first column in the information tree.
2026-03-30 21:16:00 +02:00
Kellermorph 0cd71cbe16 Conditionally save max_slaves if limit is set 2026-03-30 21:15:15 +02:00
Kellermorph 9344515d2a Refactor isFull method to simplify max_slaves logic 2026-03-30 21:14:48 +02:00
Kellermorph 9149128f7a Refactor comments and improve code formatting 2026-03-30 21:14:10 +02:00
Kellermorph 5296c1b478 Change initialization of m_max_slaves and m_contact_count 2026-03-30 21:13:26 +02:00
Laurent Trinques b4c8af55d3 Merge pull request #443 from Kellermorph/master
Auto-build doxygen docs / doxygen (push) Failing after 1m50s
Auto-build doxygen docs / deploy (push) Has been skipped
Feature: Auto-select active diagram in the elements panel tree
2026-03-29 22:04:08 +02:00
Laurent Trinques cb47094a1f Update README.md 2026-03-29 22:00:43 +02:00
Laurent Trinques 3f1db24d6d Update README.md 2026-03-29 21:58:32 +02:00
Kellermorph 1af0c1ca8b Refactor addDiagram and updateDiagramItem signatures 2026-03-29 18:14:10 +02:00
Kellermorph bea1fb4353 Refactor elements_panel to elementsPanel 2026-03-29 18:13:14 +02:00
Kellermorph 2f69716e3c Change access modifier to private for attributes
Changed access modifier of elements_panel and QAction attributes from public to private.
2026-03-29 18:12:17 +02:00
Kellermorph 277fa087bc Fix formatting in genericpanel.h method signatures 2026-03-28 14:49:31 +01:00
Kellermorph 9693df4252 Highlight current page in ProjectView on diagram activation 2026-03-28 14:49:00 +01:00
Kellermorph 6b80fbb08d Change access modifier of elements_panel to public 2026-03-28 14:48:18 +01:00
Laurent Trinques 7425c83231 Merge pull request #442 from qelectrotech/revert-441-master
Auto-build doxygen docs / doxygen (push) Failing after 1m52s
Auto-build doxygen docs / deploy (push) Has been skipped
Revert "Feature: Implement max_slaves limit for Master elements"
2026-03-27 15:33:48 +01:00
103 changed files with 47386 additions and 18211 deletions
+2 -2
View File
@@ -15,10 +15,10 @@ The main goal of the developers is to provide a libre, easy to use and effective
### Version
The current stable version is 0.90 and was released on 2023.01.06.
The current stable version is 0.100 and was released on 2026.01.25.
Once it has been officially released, the stable version is always frozen and is no longer developed.
New functionalities, bug and issue fixings are further made in the development version (currently 0.100), which can also be [downloaded](https://qelectrotech.org/download.php).
New functionalities, bug and issue fixings are further made in the development version (currently 0.100.1 or 0.200.0 if based on new Qt6 port), which can also be [downloaded](https://qelectrotech.org/download.php).
Users who want to test and take benefits from the last software implementations should use the development version. But... use it at your own risk, since things are sometimes broken or only partially implemented until they are done!
@@ -1,8 +1,7 @@
{
"id": "org.qelectrotech.QElectroTech",
"base-version": "5.15-23.08",
"runtime": "org.kde.Platform",
"runtime-version": "5.15-23.08",
"runtime-version": "5.15-25.08",
"sdk": "org.kde.Sdk",
"command": "qelectrotech",
"rename-desktop-file": "org.qelectrotech.qelectrotech.desktop",
@@ -18,51 +17,17 @@
"--socket=cups",
"--filesystem=host"
],
"cleanup": [
"/include",
"/man",
"/share/doc",
"/share/man",
"*.la",
"*.a"
],
"modules": [
{
"name": "tkinter",
"buildsystem": "simple",
"build-commands": [
"pip3 install --prefix=${FLATPAK_DEST} ."
],
"sources": [
{
"type": "git",
"url": "https://github.com/iwalton3/tkinter-standalone",
"commit": "23c793bad2429f4a81eee9f50e2d07ae845b7785"
}
],
"modules": [
{
"name": "tcl",
"sources": [
{
"type": "archive",
"url": "https://sourceforge.net/projects/tcl/files/Tcl/8.6.11/tcl8.6.11-src.tar.gz",
"sha256": "8c0486668586672c5693d7d95817cb05a18c5ecca2f40e2836b9578064088258"
}
],
"subdir": "unix",
"post-install": [
"chmod +w ${FLATPAK_DEST}/lib/libtcl8.6.so"
]
},
{
"name": "tk",
"sources": [
{
"type": "archive",
"url": "https://sourceforge.net/projects/tcl/files/Tcl/8.6.11/tk8.6.11-src.tar.gz",
"sha256": "5228a8187a7f70fa0791ef0f975270f068ba9557f57456f51eb02d9d4ea31282"
}
],
"subdir": "unix",
"post-install": [
"chmod +w ${FLATPAK_DEST}/lib/libtk8.6.so"
]
}
]
},
"tkinter.json",
"pypi-dependencies.json",
{
"name": "qelectrotech",
"buildsystem": "qmake",
@@ -76,37 +41,11 @@
},
{
"type": "patch",
"path": "patches/0001-build-Fix-the-installation-paths.patch"
"paths": [
"patches/fix-the-installation-paths.patch"
]
}
]
},
{
"name": "python3-PySimpleGUI",
"buildsystem": "simple",
"build-commands": [
"pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} PySimpleGUI"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/d0/c3/c1ce811a1e48d5e0f2df0b393ff189fae4842ec840bb6e4db79c8da55e74/PySimpleGUI-4.41.2.tar.gz",
"sha256": "cf42d9f61f28c8e790a9c031ce900a9cee5fd2f950da2f055ed36bbc487dcf11"
}
]
},
{
"name": "python3-qet-tb-generator",
"buildsystem": "simple",
"build-commands": [
"pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} qet-tb-generator"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/70/aa/ebde0dddfbde799a4e8cf0564e52f95089105a7f562739ee1d16ff5a495a/qet_tb_generator-1.3.1.tar.gz",
"sha256": "52c9836387d54bc30ea29272068ec156fc65c3905e0cb863afd9418abc3c0907"
}
]
}
}
]
}
@@ -0,0 +1,54 @@
From 5cb80674cec7363ed00bab5248b3674ca5241c2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sabri=20=C3=9Cnal?= <yakushabb@gmail.com>
Date: Fri, 20 Feb 2026 22:56:52 +0300
Subject: [PATCH] Fix appdata paper cuts
---
misc/qelectrotech.appdata.xml | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/misc/qelectrotech.appdata.xml b/misc/qelectrotech.appdata.xml
index dd06ab7..eb02119 100644
--- a/misc/qelectrotech.appdata.xml
+++ b/misc/qelectrotech.appdata.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2006-2023 The QElectroTech Team -->
-<application>
- <id type="desktop">qelectrotech.desktop</id>
+<component type="desktop-application">
+ <id>org.qelectrotech.QElectroTech</id>
+ <launchable type="desktop-id">qelectrotech.desktop</launchable>
<metadata_license>MIT</metadata_license>
<project_license>GPL-2.0-or-later</project_license>
<name>QElectroTech</name>
@@ -83,9 +84,22 @@
QET は要素と回路図に XML 形式を利用し、回路図エディタ、要素エディタ、表題欄エディタを含みます。
</p>
</description>
- <url type="homepage">http://qelectrotech.org</url>
+ <url type="homepage">https://qelectrotech.org</url>
+ <url type="bugtracker">https://qelectrotech.org/bugtracker</url>
+ <url type="vcs-browser">https://github.com/qelectrotech/qelectrotech-source-mirror</url>
+ <developer id="org.qelectrotech">
+ <name>QElectroTech</name>
+ </developer>
<screenshots>
- <screenshot type="default">http://download.tuxfamily.org/qet/screens/qelectrotech5.png</screenshot>
+ <screenshot type="default">
+ <image>https://qelectrotech.org/screenshots/qet_overview04.png</image>
+ </screenshot>
+ <screenshot>
+ <image>https://qelectrotech.org/screenshots/qet_overview06.png</image>
+ </screenshot>
+ <screenshot>
+ <image>https://qelectrotech.org/screenshots/qet_overview09.png</image>
+ </screenshot>
</screenshots>
- <updatecontact>qet@lists.tuxfamily.org</updatecontact>
-</application>
+ <update_contact>qet@lists.tuxfamily.org</update_contact>
+</component>
--
2.53.0
@@ -1,16 +1,6 @@
From 14f0685ddcf3a7d64bb85a3e9a9ac97c369bb508 Mon Sep 17 00:00:00 2001
From: Laurent Trinques <scorpio@qelectrotech.org>
Date: Sat, 26 Sep 2020 22:52:52 +0200
Subject: [PATCH] build: Fix the installation paths
---
qelectrotech.pro | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/qelectrotech.pro b/qelectrotech.pro
index 7baddbb08..5dcda04b6 100644
--- a/qelectrotech.pro
+++ b/qelectrotech.pro
diff -ruN a/qelectrotech.pro b/qelectrotech.pro
--- a/qelectrotech.pro 2023-04-20 11:47:07.695847458 +0200
+++ b/qelectrotech.pro 2023-04-20 11:51:14.843611898 +0200
@@ -5,18 +5,18 @@
# Chemins utilises pour la compilation et l'installation de QET
unix {
@@ -35,6 +25,3 @@ index 7baddbb08..5dcda04b6 100644
QET_APPDATA_PATH = 'share/appdata'
}
win32 {
--
2.35.1
@@ -0,0 +1,184 @@
commit 3bbb09a0598fc976d2bf8dac932b27740086c1bd
Author: Hubert Figuière <hub@figuiere.net>
Date: Sun Dec 21 17:49:43 2025 -0500
Port to Python 3.13
Signed-off-by: Hubert Figuière <hub@figuiere.net>
diff --git a/_tkinter.c b/_tkinter.c
index e537707..dfc5789 100644
--- a/_tkinter.c
+++ b/_tkinter.c
@@ -21,7 +21,6 @@ Copyright (C) 1994 Steen Lumholt.
*/
-#define PY_SSIZE_T_CLEAN
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
@@ -32,6 +31,9 @@ Copyright (C) 1994 Steen Lumholt.
# include "pycore_fileutils.h" // _Py_stat()
#endif
+#include "pycore_long.h" // _PyLong_IsNegative()
+#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
+
#ifdef MS_WINDOWS
#include <windows.h>
#endif
@@ -135,7 +137,7 @@ _get_tcl_lib_path()
struct stat stat_buf;
int stat_return_value;
- prefix = PyUnicode_FromWideChar(Py_GetPrefix(), -1);
+ (void) _PySys_GetOptionalAttrString("base_prefix", &prefix);
if (prefix == NULL) {
return NULL;
}
@@ -143,9 +145,11 @@ _get_tcl_lib_path()
/* Check expected location for an installed Python first */
tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
if (tcl_library_path == NULL) {
+ Py_DECREF(prefix);
return NULL;
}
tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
+ Py_DECREF(prefix);
if (tcl_library_path == NULL) {
return NULL;
}
@@ -959,7 +963,8 @@ AsObj(PyObject *value)
(unsigned char *)(void *)&wideValue,
sizeof(wideValue),
PY_LITTLE_ENDIAN,
- /* signed */ 1) == 0) {
+ /* signed */ 1,
+ /* with_exceptions */ 1) == 0) {
return Tcl_NewWideIntObj(wideValue);
}
PyErr_Clear();
@@ -1988,7 +1993,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
int v;
if (PyLong_Check(arg)) { /* int or bool */
- return PyBool_FromLong(Py_SIZE(arg) != 0);
+ return PyBool_FromLong(!_PyLong_IsZero((PyLongObject *)arg));
}
if (PyTclObject_Check(arg)) {
diff --git a/clinic/_tkinter.c.h b/clinic/_tkinter.c.h
index 9103565..f43510d 100644
--- a/clinic/_tkinter.c.h
+++ b/clinic/_tkinter.c.h
@@ -2,6 +2,8 @@
preserve
[clinic start generated code]*/
+#include "pycore_modsupport.h" // _PyArg_BadArgument()
+
PyDoc_STRVAR(_tkinter_tkapp_eval__doc__,
"eval($self, script, /)\n"
"--\n"
@@ -426,7 +428,7 @@ _tkinter_tkapp_createfilehandler(TkappObject *self, PyObject *const *args, Py_ss
goto exit;
}
file = args[0];
- mask = _PyLong_AsInt(args[1]);
+ mask = PyLong_AsInt(args[1]);
if (mask == -1 && PyErr_Occurred()) {
goto exit;
}
@@ -490,7 +492,7 @@ _tkinter_tkapp_createtimerhandler(TkappObject *self, PyObject *const *args, Py_s
if (!_PyArg_CheckPositional("createtimerhandler", nargs, 2, 2)) {
goto exit;
}
- milliseconds = _PyLong_AsInt(args[0]);
+ milliseconds = PyLong_AsInt(args[0]);
if (milliseconds == -1 && PyErr_Occurred()) {
goto exit;
}
@@ -524,7 +526,7 @@ _tkinter_tkapp_mainloop(TkappObject *self, PyObject *const *args, Py_ssize_t nar
if (nargs < 1) {
goto skip_optional;
}
- threshold = _PyLong_AsInt(args[0]);
+ threshold = PyLong_AsInt(args[0]);
if (threshold == -1 && PyErr_Occurred()) {
goto exit;
}
@@ -558,7 +560,7 @@ _tkinter_tkapp_dooneevent(TkappObject *self, PyObject *const *args, Py_ssize_t n
if (nargs < 1) {
goto skip_optional;
}
- flags = _PyLong_AsInt(args[0]);
+ flags = PyLong_AsInt(args[0]);
if (flags == -1 && PyErr_Occurred()) {
goto exit;
}
@@ -741,29 +743,29 @@ _tkinter_create(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
if (nargs < 4) {
goto skip_optional;
}
- interactive = _PyLong_AsInt(args[3]);
- if (interactive == -1 && PyErr_Occurred()) {
+ interactive = PyObject_IsTrue(args[3]);
+ if (interactive < 0) {
goto exit;
}
if (nargs < 5) {
goto skip_optional;
}
- wantobjects = _PyLong_AsInt(args[4]);
- if (wantobjects == -1 && PyErr_Occurred()) {
+ wantobjects = PyObject_IsTrue(args[4]);
+ if (wantobjects < 0) {
goto exit;
}
if (nargs < 6) {
goto skip_optional;
}
- wantTk = _PyLong_AsInt(args[5]);
- if (wantTk == -1 && PyErr_Occurred()) {
+ wantTk = PyObject_IsTrue(args[5]);
+ if (wantTk < 0) {
goto exit;
}
if (nargs < 7) {
goto skip_optional;
}
- sync = _PyLong_AsInt(args[6]);
- if (sync == -1 && PyErr_Occurred()) {
+ sync = PyObject_IsTrue(args[6]);
+ if (sync < 0) {
goto exit;
}
if (nargs < 8) {
@@ -814,7 +816,7 @@ _tkinter_setbusywaitinterval(PyObject *module, PyObject *arg)
PyObject *return_value = NULL;
int new_val;
- new_val = _PyLong_AsInt(arg);
+ new_val = PyLong_AsInt(arg);
if (new_val == -1 && PyErr_Occurred()) {
goto exit;
}
diff --git a/setup.py b/setup.py
index f379305..cf7b6ad 100644
--- a/setup.py
+++ b/setup.py
@@ -3,11 +3,11 @@ from distutils.core import setup, Extension
module1 = Extension('_tkinter',
libraries=['tcl8.6', 'tk8.6'],
sources=['_tkinter.c'],
- include_dirs=['/app/include/'])
+ include_dirs=['/app/include/', '/usr/include/python3.13/internal/'])
setup(
name='tkinter-standalone',
- version='3.11',
+ version='3.13',
description='Tkinter packaged as an external package for flatpak.',
ext_modules=[module1],
packages=["tkinter"]
+40
View File
@@ -0,0 +1,40 @@
{
"name": "pypi-dependencies",
"buildsystem": "simple",
"build-commands": [],
"modules": [
{
"name": "python3-PySimpleGUI",
"buildsystem": "simple",
"build-commands": [
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"PySimpleGUI\" --no-build-isolation"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/4d/d9/3de4b7ca71a7779e4f4a160088621b072a29d9b814a7fa9b5411571f4849/pysimplegui-5.0.8.3-py3-none-any.whl",
"sha256": "67e35ad6dd76e9369051261114f4711308e87815a0488f7fa28b37c29a546f8b"
}
]
},
{
"name": "python3-qet-tb-generator",
"buildsystem": "simple",
"build-commands": [
"pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"qet-tb-generator\" --no-build-isolation"
],
"sources": [
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/4d/d9/3de4b7ca71a7779e4f4a160088621b072a29d9b814a7fa9b5411571f4849/pysimplegui-5.0.8.3-py3-none-any.whl",
"sha256": "67e35ad6dd76e9369051261114f4711308e87815a0488f7fa28b37c29a546f8b"
},
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/63/d6/81de49a3ccec259583241fec4d79c668eff4acf9eb4d0226db36e1399f2d/qet_tb_generator-1.3.1-py3-none-any.whl",
"sha256": "80fb4af229edfd5774e61f96fa387ff394d5060abd0ca45c3c74d29de1ce9b53"
}
]
}
]
}
+58
View File
@@ -0,0 +1,58 @@
{
"//note": "The `tkinter` module is missing from the Freedesktop Sdk's Python installation",
"name": "tkinter",
"buildsystem": "simple",
"build-commands": [
"pip3 install --prefix=${FLATPAK_DEST} --no-build-isolation ."
],
"sources": [
{
"type": "git",
"url": "https://github.com/iwalton3/tkinter-standalone",
"commit": "88aa05075d90d393a29a484bce676e237d311082"
},
{
"type": "patch",
"path": "patches/tkinter-build.patch"
}
],
"modules": [
{
"name": "tcl",
"buildsystem": "autotools",
"subdir": "unix",
"post-install": [
"chmod 755 /app/lib/libtcl*.so"
],
"cleanup": [
"/bin"
],
"sources": [
{
"type": "archive",
"url": "https://prdownloads.sourceforge.net/tcl/tcl8.6.17-src.tar.gz",
"sha256": "a3903371efcce8a405c5c245d029e9f6850258a60fa3761c4d58995610949b31"
}
]
},
{
"name": "tk",
"buildsystem": "autotools",
"subdir": "unix",
"post-install": [
"chmod 755 /app/lib/libtk*.so"
],
"cleanup": [
"/bin",
"/lib/tk*/demos"
],
"sources": [
{
"type": "archive",
"url": "https://prdownloads.sourceforge.net/tcl/tk8.6.17-src.tar.gz",
"sha256": "e4982df6f969c08bf9dd858a6891059b4a3f50dc6c87c10abadbbe2fc4838946"
}
]
}
]
}
-191
View File
@@ -1,191 +0,0 @@
# Header, don't edit
NLF v6
# Start editing here
# Language ID
2067
# Font and size - dash (-) means default
-
-
# Codepage - dash (-) means ANSI code page
1252
# RTL - anything else than RTL means LTR
-
# Translation by Ronny Desmedt (any credits should go here)
# ^Branding
Nullsoft Install System %s
# ^SetupCaption
$(^Name) Installatie
# ^UninstallCaption
$(^Name) Deïnstallatie
# ^LicenseSubCaption
: Licentie overeenkomst
# ^ComponentsSubCaption
: Installatie Opties
# ^DirSubCaption
: Installatie Map
# ^InstallingSubCaption
: Installeren
# ^CompletedSubCaption
: Voltooid
# ^UnComponentsSubCaption
: Deïnstallatie Opties
# ^UnDirSubCaption
: Deïnstallatie Map
# ^ConfirmSubCaption
: Bevestigen
# ^UninstallingSubCaption
: Deïnstalleren
# ^UnCompletedSubCaption
: Voltooid
# ^BackBtn
< &Terug
# ^NextBtn
&Volgende >
# ^AgreeBtn
Ik ben &Akkoord
# ^AcceptBtn
Ik &Accepteer de licentie overeenkomst
# ^DontAcceptBtn
Ik &Accepteer de licentie overeenkomst niet
# ^InstallBtn
&Installeer
# ^UninstallBtn
&Deïnstalleer
# ^CancelBtn
Afbreken
# ^CloseBtn
&Sluiten
# ^BrowseBtn
B&laderen...
# ^ShowDetailsBtn
Toon &details
# ^ClickNext
Klik op volgende om verder te gaan.
# ^ClickInstall
Klik op installeren om de installatie te starten.
# ^ClickUninstall
Klik op deïnstalleren om de installatie te verwijderen.
# ^Name
Naam
# ^Completed
Voltooid
# ^LicenseText
Gelieve de licentie overeenkomst te lezen alvorens $(^NameDA) te installeren. Als u akkord bent met de licentie overeenkomst, klik op akkoord.
# ^LicenseTextCB
Gelieve de licentie overeenkomst te lezen alvorens $(^NameDA) te installeren. Als u akkord bent met de licentie overeenkomst, klik op onderstaande selectievakje. $_CLICK
# ^LicenseTextRB
Gelieve de licentie overeenkomst te lezen alvorens $(^NameDA) te installeren. Als u akkord bent met de licentie overeenkomst, selecteer de eerste onderstaande optie. $_CLICK
# ^UnLicenseText
Gelieve de licentie overeenkomst te lezen alvorens $(^NameDA) te deïnstalleren. Als u akkord bent met de licentie overeenkomst, klik op akkoord.
# ^UnLicenseTextCB
Gelieve de licentie overeenkomst te lezen alvorens $(^NameDA) te deïnstalleren. Als u akkord bent met de licentie overeenkomst, klik op onderstaande selectievakje. $_CLICK
# ^UnLicenseTextRB
Gelieve de licentie overeenkomst te lezen alvorens $(^NameDA) te deïnstalleren. Als u akkord bent met de licentie overeenkomst, selecteer de eerste onderstaande optie. $_CLICK
# ^Custom
Aangepast
# ^ComponentsText
Selecteer de onderdelen die u wilt installeren en deselecteer de onderdelen die u niet wilt installeren. $_CLICK
# ^ComponentsSubText1
Selecteer een installatie type:
# ^ComponentsSubText2_NoInstTypes
Selecteer de onderdelen om te installeren:
# ^ComponentsSubText2
Of, selecteer optionelen onderdelen die u wilt installeren:
# ^UnComponentsText
Selecteer de onderdelen die u wilt deïnstalleren en deselecteer de onderdelen die u niet wilt deïinstalleren. $_CLICK
# ^UnComponentsSubText1
Selecteer een deïnstallatie type:
# ^UnComponentsSubText2_NoInstTypes
Selecteer de onderdelen om te deïnstalleren:
# ^UnComponentsSubText2
Of, selecteer optionelen onderdelen die u wilt deïnstalleren:
# ^DirText
De installatie van $(^NameDA) wordt in volgende map uitgevoerd. Om in een andere map te installeren, klik op bladeren om een andere map te selecteren. $_CLICK
# ^DirSubText
Installatie map
# ^DirBrowseText
Selecteerd de map om $(^NameDA) in te installeren:
# ^UnDirText
De deïnstallatie van $(^NameDA) in de volgende map. Om een andere map te deïnstalleren, klik op bladren om een andere map te selecteren. $_CLICK
# ^UnDirSubText
""
# ^UnDirBrowseText
Selecteer en map om $(^NameDA) van te deînstalleren:
# ^SpaceAvailable
"Beschikbare ruimte: "
# ^SpaceRequired
"Benodigde ruimte: "
# ^UninstallingText
$(^NameDA) wordt gedeïnstalleerd uit volgende map. $_CLICK
# ^UninstallingSubText
Deïnstalleren van:
# ^FileError
Fout bij openen van bestand om te schrijven: \r\n\r\n$0\r\n\r\nKlik op afbreken om de installatie te stoppen,\r\nOpnieuw om te proberen, of\r\nNegeren om dit bestand over te slaan.
# ^FileError_NoIgnore
Fout bij openen van bestand om te schrijven: \r\n\r\n$0\r\n\r\nOpnieuw om te proberen, of\r\nAfbreken om de installatie te stoppen.
# ^CantWrite
"Kan niet schrijven: "
# ^CopyFailed
Kopieren mislukt
# ^CopyTo
"Copier naar "
# ^Registering
"Registreren: "
# ^Unregistering
"Deregistreren: "
# ^SymbolNotFound
"Kan symbool niet vinden: "
# ^CouldNotLoad
"Kan niet laden: "
# ^CreateFolder
"Map maken: "
# ^CreateShortcut
"Snelkoppeling maken: "
# ^CreatedUninstaller
"Doe deïnstallatie: "
# ^Delete
"Verwijder bestanden: "
# ^DeleteOnReboot
Verwijder bij herstarten: "
# ^ErrorCreatingShortcut
"Fout bij maken snelkoppeling: "
# ^ErrorCreating
"Fout bij maken: "
# ^ErrorDecompressing
Fout bij uitpakken gegevens! Beschadigd bestand?
# ^ErrorRegistering
Fout bij registreren DLL
# ^ExecShell
"ExecShell: "
# ^Exec
"Uitvoeren: "
# ^Extract
"Extract: "
# ^ErrorWriting
Fout: fout bij schrijven naar bestand "
# ^InvalidOpcode
Installie beschadigd: niet toegestane opcode
# ^NoOLE
"Geen OLE voor: "
# ^OutputFolder
"Bestemmings map: "
# ^RemoveFolder
"Verwijder mapr: "
# ^RenameOnReboot
"Hernoem bij opstarten: "
# ^Rename
"Hernoem: "
# ^Skipped
Overgeslagen: "
# ^CopyDetails
Copier details naar klembord
# ^LogInstall
Log instaltie proces
# ^Byte
B
# ^Kilo
K
# ^Mega
M
# ^Giga
G
-128
View File
@@ -1,128 +0,0 @@
;Language:Dutch_Belgium (2067)
;By Ronny Desmedt
!insertmacro LANGFILE "Dutch_Belgium" "Dutch_Belgium"
!ifdef MUI_WELCOMEPAGE
${LangFileString} MUI_TEXT_WELCOME_INFO_TITLE "Welkom bij $(^NameDA) installatie Wizard"
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Deze wizard zal u begeleiden bij de installatie van $(^NameDA).$\r$\n$\r$\nHet is aanbevol dat u alle andere programmas afsluit voordat u deze installatie uitvoerd. Dit geeft de mogelijkheid om relevante systeem bestanden bij te werken zonder dat uw systeem terug moet opstarten.$\r$\n$\r$\n$_CLICK"
!endif
!ifdef MUI_UNWELCOMEPAGE
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TITLE "Welkom bij de $(^NameDA) deïnstallatie wizard"
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Deze wizard zal u begeleiden bij de deïnstallatie van $(^NameDA).$\r$\n$\r$\nControleer of $(^NameDA) is afgesloten alvorens de deïnstallatie te starten.$\r$\n$\r$\n$_CLICK"
!endif
!ifdef MUI_LICENSEPAGE
${LangFileString} MUI_TEXT_LICENSE_TITLE "Licentie overeenkomst"
${LangFileString} MUI_TEXT_LICENSE_SUBTITLE "Gelieve de licentie te lezen alvorens U $(^NameDA) installeert."
${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM "Klik op akkoord om de overeenkomst te aanvaarden. U moet de overeenkomst aanvaarden om $(^NameDA) te installeren."
${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX "Als u de voorwaarden van de overeenkomst aanvaard, Klik op onderstaande selectievakje. U moet de overeenkomst aanvaarden om $(^NameDA) te installeren. $_CLICK"
${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "Als u de voorwaarden van de overeenkomst aanvaard, selecteer de eerste onderstaande optie. U moet de overeenkomst aanvaarden om $(^NameDA) te installeren. $_CLICK"
!endif
!ifdef MUI_UNLICENSEPAGE
${LangFileString} MUI_UNTEXT_LICENSE_TITLE "Licentie overeenkomst"
${LangFileString} MUI_UNTEXT_LICENSE_SUBTITLE "Gelieve de licentie overeenkomst te herlezen alvorens met de deïnstallatie van $(^NameDA) verder te doen."
${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM "Klik op akkoord om de overeenkomst te aanvaarden. U moet de overeenkomst aanvaarden om $(^NameDA) te deïnstalleren."
${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX "Als u de voorwaarden van de overeenkomst aanvaard, Klik op onderstaande selectievakje. U moet de overeenkomst aanvaarden om $(^NameDA) te deïnstalleren. $_CLICK"
${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "Als u de voorwaarden van de overeenkomst aanvaard, selecteer de eerste onderstaande optie. U moet de overeenkomst aanvaarden om $(^NameDA) te deïnstalleren. $_CLICK"
!endif
!ifdef MUI_LICENSEPAGE | MUI_UNLICENSEPAGE
${LangFileString} MUI_INNERTEXT_LICENSE_TOP "Gebruik pagina neer om de rest van de overeenkomst te lezen."
!endif
!ifdef MUI_COMPONENTSPAGE
${LangFileString} MUI_TEXT_COMPONENTS_TITLE "Kies onderdelen"
${LangFileString} MUI_TEXT_COMPONENTS_SUBTITLE "Kies de onderdelen van $(^NameDA) die u wilt installeren."
!endif
!ifdef MUI_UNCOMPONENTSPAGE
${LangFileString} MUI_UNTEXT_COMPONENTS_TITLE "Kies onderdelen"
${LangFileString} MUI_UNTEXT_COMPONENTS_SUBTITLE "Kies de onderdelen van $(^NameDA) die u wilt deïnstalleren."
!endif
!ifdef MUI_COMPONENTSPAGE | MUI_UNCOMPONENTSPAGE
${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE "Beschrijving"
!ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Beweeg de muisaanwijzer over de onderdelen om de beschrijving te zien."
!else
${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Beweeg de muisaanwijzer over de onderdelen om de beschrijving te zien."
!endif
!endif
!ifdef MUI_DIRECTORYPAGE
${LangFileString} MUI_TEXT_DIRECTORY_TITLE "Kies een installatie locatie"
${LangFileString} MUI_TEXT_DIRECTORY_SUBTITLE "Kies een map waar U $(^NameDA) wilt installeren."
!endif
!ifdef MUI_UNDIRECTORYPAGE
${LangFileString} MUI_UNTEXT_DIRECTORY_TITLE "Kies een deïnstallatie locatie"
${LangFileString} MUI_UNTEXT_DIRECTORY_SUBTITLE "Kies een map waar U $(^NameDA) wilt deïnstalleren."
!endif
!ifdef MUI_INSTFILESPAGE
${LangFileString} MUI_TEXT_INSTALLING_TITLE "Installeren"
${LangFileString} MUI_TEXT_INSTALLING_SUBTITLE "Even gedult terwijl $(^NameDA) wordt geinstalleerd."
${LangFileString} MUI_TEXT_FINISH_TITLE "Installatie voltooid"
${LangFileString} MUI_TEXT_FINISH_SUBTITLE "De installatie is succesvol afgerond."
${LangFileString} MUI_TEXT_ABORT_TITLE "Installatie is afgebroken"
${LangFileString} MUI_TEXT_ABORT_SUBTITLE "De installatie is niet voltooid."
!endif
!ifdef MUI_UNINSTFILESPAGE
${LangFileString} MUI_UNTEXT_UNINSTALLING_TITLE "DeïnEven geduld terwijl $(^NameDA) wordt gedeïnstalleerd."
${LangFileString} MUI_UNTEXT_FINISH_TITLE "Deïnstallatie voltooid"
${LangFileString} MUI_UNTEXT_FINISH_SUBTITLE "Deïnstallatie succesvol afgerond."
${LangFileString} MUI_UNTEXT_ABORT_TITLE "Deïnstallatie onderbroken"
${LangFileString} MUI_UNTEXT_ABORT_SUBTITLE "Deïnstallatie is niet voltooid."
!endif
!ifdef MUI_FINISHPAGE
${LangFileString} MUI_TEXT_FINISH_INFO_TITLE "Voltooien van de $(^NameDA) installatie Wizard"
${LangFileString} MUI_TEXT_FINISH_INFO_TEXT "$(^NameDA) is geinstalleerd op uw computer.$\r$\n$\r$\nKlik op einde om de installatie wizard af te sluiten."
${LangFileString} MUI_TEXT_FINISH_INFO_REBOOT "Uw computer moet herstarten op de installatie van $(^NameDA) te voltooien. Wilt u nu opnieuw opstarten?"
!endif
!ifdef MUI_UNFINISHPAGE
${LangFileString} MUI_UNTEXT_FINISH_INFO_TITLE "Voltooien van de $(^NameDA) deïnstallatie wizard"
${LangFileString} MUI_UNTEXT_FINISH_INFO_TEXT "$(^NameDA) is gedeïnstalleerd op uw computer.$\r$\n$\r$\nKlik op einde om de installatie wizard af te sluiten."
${LangFileString} MUI_UNTEXT_FINISH_INFO_REBOOT "Uw computer moet herstarten op de deïnstallatie van $(^NameDA)te voltooien. Wilt u nu opnieuw opstarten?"
!endif
!ifdef MUI_FINISHPAGE | MUI_UNFINISHPAGE
${LangFileString} MUI_TEXT_FINISH_REBOOTNOW "Nu herstarten"
${LangFileString} MUI_TEXT_FINISH_REBOOTLATER "Ik wil later herstarten"
${LangFileString} MUI_TEXT_FINISH_RUN "&Starten $(^NameDA)"
${LangFileString} MUI_TEXT_FINISH_SHOWREADME "&Toon leesmij"
${LangFileString} MUI_BUTTONTEXT_FINISH "&Einde"
!endif
!ifdef MUI_STARTMENUPAGE
${LangFileString} MUI_TEXT_STARTMENU_TITLE "Kies start menu map"
${LangFileString} MUI_TEXT_STARTMENU_SUBTITLE "Kies een map in start menu voor de snelkoppeling van $(^NameDA)."
${LangFileString} MUI_INNERTEXT_STARTMENU_TOP "Kies een map in start menu waar u de programma snelkoppelingen wilt aanmaken. U kan ook de naam van een nieuwe map opgeven."
${LangFileString} MUI_INNERTEXT_STARTMENU_CHECKBOX "Maak geen snelkoppelingen"
!endif
!ifdef MUI_UNCONFIRMPAGE
${LangFileString} MUI_UNTEXT_CONFIRM_TITLE "Deïnstalleer$(^NameDA)"
${LangFileString} MUI_UNTEXT_CONFIRM_SUBTITLE "Verwijder $(^NameDA) van uw computer."
!endif
!ifdef MUI_ABORTWARNING
${LangFileString} MUI_TEXT_ABORTWARNING "Weet u zeker dat U installatie van $(^Name) wilt afbreken?"
!endif
!ifdef MUI_UNABORTWARNING
${LangFileString} MUI_UNTEXT_ABORTWARNING "Weet u zeker dat U de deïnstallatie van $(^Name)wilt afbreken?"
!endif
!ifdef MULTIUSER_INSTALLMODEPAGE
${LangFileString} MULTIUSER_TEXT_INSTALLMODE_TITLE "Kies gebruikers"
${LangFileString} MULTIUSER_TEXT_INSTALLMODE_SUBTITLE "Kies voor welke gebruikers U $(^NameDA) wilt installeren."
${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_TOP "Kies of U $(^NameDA) alleen voor u zelf of voor alle gebruikers op deze computer wilt installeren. $(^ClickNext)"
${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS "Installeer voor iedereen die deze computer gebruikt"
${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER "Installeer alleen voor mij"
!endif
+118
View File
@@ -0,0 +1,118 @@
# Migration NSIS 2.x → 3.x — QElectroTech
## Fichiers modifiés
| Fichier | Changement |
|---|---|
| `QET64.nsi` | Migration complète (voir détails ci-dessous) |
| `lang_extra_fr.nsh` | Réencodé ISO-8859-1 → UTF-8 |
| `lang_extra.nsh` | Inchangé (déjà UTF-8) |
---
## Détail des changements dans `QET64.nsi`
### 1. `SetCompressor` déplacé en tête de fichier
**NSIS 3 exige** que `SetCompressor` apparaisse avant toute `Section` ou `Function`.
Avant il était après les `!include` et `!define` — cela fonctionnait en NSIS 2 mais
génère un avertissement/erreur en NSIS 3.
```nsis
; ✅ NSIS 3 — en tout premier
SetCompressor /FINAL /SOLID lzma
```
### 2. `XPStyle on` supprimé → remplacé par `ManifestSupportedOS`
`XPStyle on` est **retiré en NSIS 3**. Il était utilisé pour activer les styles visuels
Windows XP/Vista. NSIS 3 gère cela via le manifeste de l'exécutable :
```nsis
; ✅ NSIS 3
ManifestSupportedOS all
ManifestDPIAware true
```
### 3. `Var /GLOBAL` déclarées au niveau global
En NSIS 2, des `Var /GLOBAL` à l'intérieur d'une `Section` compilaient sans erreur.
En NSIS 3, les variables doivent être déclarées **au niveau du script** (avant toute section).
```nsis
; ✅ NSIS 3 — déclaration globale
Var final_qet_exe
Var final_project_ico
Var final_element_ico
Var final_titleblock_ico
```
### 4. `SetRegView 64` ajouté dans `.onInit`, section cachée, et `un.onInit`
En NSIS 3, sur un système 64 bits, **la redirection de registre WOW6432Node est active
par défaut**. Sans `SetRegView 64`, les clés HKLM atterrissent dans
`HKLM\SOFTWARE\Wow6432Node\` au lieu de `HKLM\SOFTWARE\`.
Ajouté à trois endroits :
- `Function .onInit` → pour lire la clé d'installation existante
- Section cachée (registry/shortcuts) → avant les `WriteRegStr`
- `Section "Uninstall"` → pour supprimer les bonnes clés
- `Function un.onInit` → cohérence avec l'installation
### 5. Icônes MUI mises à jour
Les icônes `XPUI-install.ico` / `XPUI-uninstall.ico` sont remplacées par les nouvelles
icônes NSIS 3 :
```nsis
; ✅ NSIS 3
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\nsis3-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\nsis3-uninstall.ico"
```
> Les anciennes icônes XPUI sont encore présentes pour compatibilité ascendante, mais
> les nouvelles sont recommandées.
### 6. `${IfNot} ${RunningX64}` — syntaxe clarifiée
Remplacement du bloc `${If}/${Else}/${EndIf}` moins lisible par `${IfNot}` plus concis :
```nsis
; ✅ NSIS 3 — idiome recommandé
${IfNot} ${RunningX64}
MessageBox MB_OK|MB_ICONSTOP $(wrongArch)
Abort
${EndIf}
```
### 7. URLs HTTP → HTTPS
Les URLs `http://qelectrotech.org/` ont été mises à jour en `https://qelectrotech.org/`
(cosmétique, sans impact sur la compilation).
### 8. `lang_extra_fr.nsh` — Réencodage ISO-8859-1 → UTF-8
NSIS 3 est **Unicode natif** : tous les fichiers `.nsh` doivent être encodés en UTF-8
(avec ou sans BOM). Le fichier `lang_extra_fr.nsh` était en ISO-8859-1 — il a été
converti en UTF-8.
> **Commande utilisée :** `iconv -f ISO-8859-1 -t UTF-8 lang_extra_fr.nsh`
---
## Ce qui N'A PAS changé (déjà compatible NSIS 3)
- `!include "MUI2.nsh"` — inchangé ✅
- `!define MUI_LANGDLL_ALLLANGUAGES` — toujours supporté ✅
- `!insertmacro MUI_RESERVEFILE_LANGDLL` — inchangé ✅
- `FileFunc.nsh` / macro `Locate` — inchangé ✅
- `RequestExecutionLevel admin` — inchangé ✅
- `InstallDir "$PROGRAMFILES64\..."` — inchangé ✅
- Structure Sections / SubSections — inchangée ✅
- `!insertmacro MUI_FUNCTION_DESCRIPTION_*` — inchangé ✅
- Toutes les `LangString` — inchangées ✅
- `Dutch_Belgium` via `Contrib/` — inchangé ✅
---
## Checklist avant compilation avec NSIS 3
- [ ] NSIS 3.x installé (https://nsis.sourceforge.io/)
- [ ] Tous les plugins utilisés sont la version Unicode/NSIS3
- `FileFunc.nsh` : fourni avec NSIS 3 ✅
- `x64.nsh` : fourni avec NSIS 3 ✅
- `MUI2.nsh` : fourni avec NSIS 3 ✅
- [ ] `lang_extra.nsh` et `lang_extra_fr.nsh` encodés en UTF-8
- [ ] Le fichier `Contrib/Dutch_Belgium.nlf` / `.nsh` est placé dans
`%NSIS%\Contrib\Language files\` ou référencé via un chemin relatif
+505 -410
View File
@@ -1,410 +1,505 @@
; this file is part of installer for QElectroTech
; Copyright (C)2015 QElectroTech Team <scorpio@qelectrotech.org>
;
; This program 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.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
; WebSite : http://qelectrotech.org/
;--------------------------------
;Include Modern UI
!include x64.nsh
!include "MUI2.nsh"
!include "FileFunc.nsh"
!insertmacro Locate
!include FileFunc.nsh
!insertmacro GetParameters
!insertmacro GetOptions
!ifndef PROC
!define PROC 32 ;
!endif
; MUI Settings
;--------------------------------
;General
; General Product Description Definitions
!define SOFT_NAME "QElectroTech"
!define SOFT_VERSION "0.5-dev_x86_64-win64+4094"
!define SOFT_WEB_SITE "http://qelectrotech.org/"
!define SOFT_BUILD "1"
SetCompressor /final /solid lzma
CRCCheck force
XPStyle on
BrandingText "${SOFT_NAME}-${SOFT_VERSION}-${SOFT_BUILD}" ; Shows in the Bottom Left of the installer
;Name and file
Name "${SOFT_NAME} ${SOFT_VERSION}"
OutFile "Installer_${SOFT_NAME}-${SOFT_VERSION}-${SOFT_BUILD}.exe"
;Default installation folder
InstallDir "$PROGRAMFILES64\${SOFT_NAME}"
;Get installation folder from registry if available
InstallDirRegKey HKCU "Software\${SOFT_NAME}" ""
;Request application privileges for Windows Vista
; we request for admin because we write stuff into the registry
RequestExecutionLevel admin
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\XPUI-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\XPUI-uninstall.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP ".\images\wizard.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP_NOSTRETCH
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP ".\images\header.bmp" ; optional
;--------------------------------
;Language Selection Dialog Settings
;Remember the installer language
!define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
!define MUI_LANGDLL_REGISTRY_KEY "Software\${SOFT_NAME}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
;--------------------------------
;Pages
!define MUI_COMPONENTSPAGE_SMALLDESC
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "files\LICENSE"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
; Finish page and checkbox to run QElectroTech
!define MUI_FINISHPAGE_RUN "$INSTDIR\Lancer QET.bat"
!define MUI_FINISHPAGE_RUN_NOTCHECKED
!define MUI_FINISHPAGE_RUN_TEXT "$(Check)"
!insertmacro MUI_PAGE_FINISH
;--------------------------------
;Languages
;Since NSIS 2.26, the language selection dialog of Modern UI hides languages unsupported by the user's selected codepage by default.
;To revert to the old behavior and display all languages, no matter what the user will see when they're selected, use MUI_LANGDLL_ALLLANGUAGES.
!define MUI_LANGDLL_ALLLANGUAGES
; For consistency, we limit the installer to languages supported by QElectroTech itself
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
!insertmacro MUI_LANGUAGE "Korean"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "Spanish"
!insertmacro MUI_LANGUAGE "Russian"
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "Czech"
!insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "Greek"
!insertmacro MUI_LANGUAGE "Arabic"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Italian"
!insertmacro MUI_LANGUAGE "Romanian"
!insertmacro MUI_LANGUAGE "Catalan"
!insertmacro MUI_LANGUAGE "Croatian"
!insertmacro MUI_LANGUAGE "Dutch"
!insertmacro MUI_LANGUAGE "Dutch_Belgium"
!insertmacro MUI_LANGUAGE "Danish"
!insertmacro MUI_RESERVEFILE_LANGDLL
!include lang_extra.nsh
!include lang_extra_fr.nsh
SetOverwrite on
Section "Main Program"
SectionIn RO ; Read only, always installed
Setoutpath "$INSTDIR\bin\"
File "./files/bin/${SOFT_NAME}.exe"
Setoutpath "$INSTDIR"
File "./files/ChangeLog"
File "./files/CREDIT"
File "./files/ELEMENTS.LICENSE"
File "./files/LICENSE"
File "./files/qet_uninstall_file_associations.reg"
File "./files/README"
File "./files/register_filetypes.bat"
File "Lancer QET.bat"
SetOutPath "$INSTDIR"
File /r "./files/ico"
SectionEnd
;---------------------------
SetOverwrite on
SubSection "$(Elements)" SEC01
SetOverwrite on
Section "$(Electric)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/10_electric"
SectionEnd
SetOverwrite on
Section "$(Logic)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/20_logic"
SectionEnd
SetOverwrite on
Section "$(Hydraulic)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/30_hydraulic"
SectionEnd
SetOverwrite on
Section "$(Pneumatic)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/50_pneumatic"
SectionEnd
;---------------------------------
SubSection "$(Energy)"
SetOverwrite on
Section "$(water)"
SetOutPath "$INSTDIR\elements\60_energy"
File /r "./files/elements/60_energy/11_water"
File /r "./files/elements/60_energy/"
SectionEnd
SetOverwrite on
Section "$(Refrigeration)"
SetOutPath "$INSTDIR\elements\60_energy"
File /r "./files/elements/60_energy/21_refrigeration"
File /r "./files/elements/60_energy/"
SectionEnd
SetOverwrite on
Section "$(Solar_thermal)"
SetOutPath "$INSTDIR\elements\60_energy"
File /r "./files/elements/60_energy/31_solar_thermal"
File /r "./files/elements/60_energy/"
SectionEnd
SubSectionEnd
SubSectionEnd
;-------------------------------
SetOverwrite on
Section "$(Lang)" SEC02
SetOutPath "$INSTDIR\lang"
File "./files/lang/*.qm"
SectionEnd
SetOverwrite on
Section "$(Titleblocks)" SEC03
SetOutPath "$INSTDIR"
File /r "./files/titleblocks"
SectionEnd
SetOverwrite on
Section "$(Examples)" SEC04
SetOutPath "$INSTDIR"
File /r "./files/examples"
SectionEnd
;--------------------------------
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC01} $(var1)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC02} $(var2)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC03} $(var3)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC04} $(var4)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
;Installer Sections
Section ""
SetOutPath "$INSTDIR"
;Store installation folder
WriteRegStr HKCU "Software\${SOFT_NAME}" "" $INSTDIR
; write uninstall strings
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}" "DisplayName" "${SOFT_NAME} (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}" "UninstallString" '"$INSTDIR\Uninstall.exe"'
;Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
SetRegView 64
; get the final path for the icons and the launch script
Var /GLOBAL final_qet_exe
Var /GLOBAL final_project_ico
Var /GLOBAL final_element_ico
Var /GLOBAL final_titleblock_ico
StrCpy $final_qet_exe "$INSTDIR\Lancer QET.bat"
StrCpy $final_project_ico "$INSTDIR\ico\application-x-qet-project.ico"
StrCpy $final_element_ico "$INSTDIR\ico\application-x-qet-element.ico"
StrCpy $final_titleblock_ico "$INSTDIR\ico\application-x-qet-titleblock.ico"
; write file associations registry keys
WriteRegStr HKEY_CLASSES_ROOT "Applications\qelectrotech.exe\shell\open\command" "" "$\"$final_qet_exe$\" $\"%1$\""
WriteRegStr HKEY_CLASSES_ROOT ".qet" "" "qet_diagram_file"
WriteRegStr HKEY_CLASSES_ROOT "qet_diagram_file" "" "Diagram QET"
WriteRegDWORD HKEY_CLASSES_ROOT "qet_diagram_file" "EditFlags" 0x00000000
WriteRegDWORD HKEY_CLASSES_ROOT "qet_diagram_file" "BrowserFlags" 0x00000008
WriteRegStr HKEY_CLASSES_ROOT "qet_diagram_file\DefaultIcon" "" "$final_project_ico"
WriteRegStr HKEY_CLASSES_ROOT "qet_diagram_file\shell\open\command" "" "$\"$final_qet_exe$\" $\"%1$\""
WriteRegStr HKEY_CLASSES_ROOT ".elmt" "" "qet_element_file"
WriteRegStr HKEY_CLASSES_ROOT "qet_element_file" "" "Element QET"
WriteRegDWORD HKEY_CLASSES_ROOT "qet_element_file" "EditFlags" 0x00000000
WriteRegDWORD HKEY_CLASSES_ROOT "qet_element_file" "BrowserFlags" 0x00000008
WriteRegStr HKEY_CLASSES_ROOT "qet_element_file\DefaultIcon" "" "$final_element_ico"
WriteRegStr HKEY_CLASSES_ROOT "qet_element_file\shell\open\command" "" "$\"$final_qet_exe$\" $\"%1$\""
WriteRegStr HKEY_CLASSES_ROOT ".titleblock" "" "qet_titleblock_file"
WriteRegStr HKEY_CLASSES_ROOT "qet_titleblock_file" "" "Titleblock QET"
WriteRegDWORD HKEY_CLASSES_ROOT "qet_titleblock_file" "EditFlags" 0x00000000
WriteRegDWORD HKEY_CLASSES_ROOT "qet_titleblock_file" "BrowserFlags" 0x00000008
WriteRegStr HKEY_CLASSES_ROOT "qet_titleblock_file\DefaultIcon" "" "$final_titleblock_ico"
WriteRegStr HKEY_CLASSES_ROOT "qet_titleblock_file\shell\open\command" "" "$\"$final_qet_exe$\" $\"%1$\""
SetShellVarContext all ; all users
; shortcuts in the start menu
CreateDirectory "$SMPROGRAMS\${SOFT_NAME}"
CreateDirectory "$SMPROGRAMS\${SOFT_NAME}\Manual"
CreateDirectory "$SMPROGRAMS\${SOFT_NAME}\Upgrade"
CreateShortCut "$SMPROGRAMS\${SOFT_NAME}\QElectroTech.lnk" "$INSTDIR\Lancer QET.bat" 0 "$INSTDIR\ico\qelectrotech.ico"
CreateShortCut "$SMPROGRAMS\${SOFT_NAME}\Uninstall QElectroTech.lnk" "$INSTDIR\Uninstall.exe"
; TODO : add the QuickStart Guide (or any other documentation) when available
; shortcut on the desktop
CreateShortCut "$DESKTOP\QElectroTech.lnk" "$INSTDIR\Lancer QET.bat" 0 "$INSTDIR\ico\qelectrotech.ico"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Manual\Manual_English.url" "InternetShortcut" "URL" "https://download.qelectrotech.org/qet/manual_0.7/build/index.html"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Manual\Manual_Russian.url" "InternetShortcut" "URL" "https://download.qelectrotech.org/qet/joshua/html/QET_ru.html"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Upgrade\Download.url" "InternetShortcut" "URL" "https://download.qelectrotech.org/qet/builds/nightly/"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Donate.url" "InternetShortcut" "URL" "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZZHC9D7C3MDPC"
;changing $INSTDIR\elements\ *.elmt to read-only attribute
${Locate} "$INSTDIR\elements\" "/L=FD /M=*.elmt" "LocateCallback"
IfErrors 0 +2
;MessageBox MB_OK "Error"
SectionEnd
Function LocateCallback
SetFileAttributes $R9 FILE_ATTRIBUTE_READONLY
Push $0
FunctionEnd
;--------------------------------
;Installer Functions
Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY
${If} ${RunningX64}
${Else}
MessageBox MB_OK|MB_ICONSTOP $(wrongArch)
Abort $(wrongArch)
${EndIf}
;Auto-uninstall old before installing new
ReadRegStr $R0 HKLM \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}" \
"UninstallString"
StrCmp $R0 "" done
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
"$(installed)" \
IDOK uninst
Abort
;Run the uninstaller
uninst:
ClearErrors
ExecWait '$R0 _?=$INSTDIR' ;Do not copy the uninstaller to a temp file
IfErrors no_remove_uninstaller done
;You can either use Delete /REBOOTOK in the uninstaller or add some code
;here to remove the uninstaller. Use a registry key to check
;whether the user has chosen to uninstall. If you are using an uninstaller
;components page, make sure all sections are uninstalled.
no_remove_uninstaller:
done:
FunctionEnd
;--------------------------------
;Descriptions
;USE A LANGUAGE STRING IF YOU WANT YOUR DESCRIPTIONS TO BE LANGAUGE SPECIFIC
;Assign descriptions to sections
;!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
; !insertmacro MUI_DESCRIPTION_TEXT ${CopyFiles} "CopyFiles"
;!insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
;Uninstaller Section
Section "Uninstall"
SetShellVarContext all ; all users
; remove start menu shortcuts
RMDir /r "$SMPROGRAMS\${SOFT_NAME}"
; remove shortcut on the desktop
Delete "$DESKTOP\QElectroTech.lnk"
; remove the application files
Delete "$INSTDIR\*.*"
RMDir /r "$INSTDIR"
;remove installation registry keys
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}"
DeleteRegKey /ifempty HKCU "Software\${SOFT_NAME}"
; remove file associations registry keys
DeleteRegKey HKEY_CLASSES_ROOT "Applications\qelectrotech.exe"
DeleteRegKey HKEY_CLASSES_ROOT ".qet"
DeleteRegKey HKEY_CLASSES_ROOT "qet_diagram_file"
DeleteRegKey HKEY_CLASSES_ROOT ".elmt"
DeleteRegKey HKEY_CLASSES_ROOT "qet_element_file"
DeleteRegKey HKEY_CLASSES_ROOT ".titleblock"
DeleteRegKey HKEY_CLASSES_ROOT "qet_titleblock_file"
IfFileExists "$INSTDIR" 0 NoErrorMsg
;MessageBox MB_OK "Note: $INSTDIR could not be removed!" IDOK 0 ; skipped if file doesn't exist
NoErrorMsg:
SectionEnd
;--------------------------------
;Uninstaller Functions
Function un.onInit
!insertmacro MUI_UNGETLANGUAGE
FunctionEnd
; this file is part of installer for QElectroTech
; Copyright (C)2015 QElectroTech Team <scorpio@qelectrotech.org>
;
; This program 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.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
; WebSite : https://qelectrotech.org/
;==============================================================================
; NSIS 3.x compatibility notes:
; - Unicode is native in NSIS 3 (no need for Unicode installer plugin)
; - XPStyle is deprecated/removed; ManifestSupportedOS replaces it
; - SetCompressor must appear before any Section/Function
; - SetRegView 64 moved to top of the hidden section (before WriteRegStr)
; - x64.nsh is still available but ${RunningX64} is now also in x64.nsh
; - MUI2.nsh is unchanged; MUI_LANGDLL_ALLLANGUAGES is still valid
; - FileFunc.nsh / Locate macro: unchanged
; - Var /GLOBAL must be declared at global scope, not inside a Section
;==============================================================================
;--------------------------------
; NSIS 3 requires SetCompressor BEFORE any Section or Function
SetCompressor /FINAL /SOLID lzma
;--------------------------------
; Includes
!include x64.nsh
!include "MUI2.nsh"
!include "FileFunc.nsh"
!insertmacro Locate
!insertmacro GetParameters
!insertmacro GetOptions
;--------------------------------
; NSIS 3: Unicode is the default. The installer binary will be Unicode.
; No extra plugin needed.
!ifndef PROC
!define PROC 64
!endif
;--------------------------------
; General Product Description Definitions
!define SOFT_NAME "QElectroTech"
!define SOFT_VERSION "0.5-dev_x86_64-win64+4094"
!define SOFT_WEB_SITE "https://qelectrotech.org/"
!define SOFT_BUILD "1"
;--------------------------------
; General settings
CRCCheck force
BrandingText "${SOFT_NAME}-${SOFT_VERSION}-${SOFT_BUILD}"
; NSIS 3: XPStyle is removed. Use ManifestSupportedOS to declare modern OS support.
; This replaces "XPStyle on" and enables proper DPI awareness + visual styles.
ManifestSupportedOS all
ManifestDPIAware true
; Name and output file
Name "${SOFT_NAME} ${SOFT_VERSION}"
OutFile "Installer_${SOFT_NAME}-${SOFT_VERSION}-${SOFT_BUILD}.exe"
; Default installation folder
InstallDir "$PROGRAMFILES64\${SOFT_NAME}"
; Get installation folder from registry if available
; NSIS 3: InstallDirRegKey still works, but SetRegView 64 must be set at
; runtime (in .onInit) to read 64-bit registry hive correctly.
InstallDirRegKey HKCU "Software\${SOFT_NAME}" ""
; Request admin privileges (required for HKLM / file associations)
RequestExecutionLevel admin
;--------------------------------
; Declare global variables at script scope (NSIS 3 requirement)
; In NSIS 2 these could be declared inside a Section; that still compiles
; in NSIS 3 but triggers a warning. Declare them here.
Var final_qet_exe
Var final_project_ico
Var final_element_ico
Var final_titleblock_ico
;--------------------------------
; MUI Interface Settings
!define MUI_ABORTWARNING
; NSIS 3 ships updated icons; XPUI icons are still present for compatibility.
; You may switch to the modern ones:
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\nsis3-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\nsis3-uninstall.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP ".\images\wizard.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP_NOSTRETCH
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP ".\images\header.bmp"
;--------------------------------
; Language Selection Dialog Settings (remember chosen language in registry)
!define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
!define MUI_LANGDLL_REGISTRY_KEY "Software\${SOFT_NAME}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
;--------------------------------
; Pages
!define MUI_COMPONENTSPAGE_SMALLDESC
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "files\LICENSE"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
; Finish page checkbox to launch QElectroTech
!define MUI_FINISHPAGE_RUN "$INSTDIR\Lancer QET.bat"
!define MUI_FINISHPAGE_RUN_NOTCHECKED
!define MUI_FINISHPAGE_RUN_TEXT "$(Check)"
!insertmacro MUI_PAGE_FINISH
;--------------------------------
; Languages
; NSIS 3: MUI_LANGDLL_ALLLANGUAGES is still supported and works as before.
!define MUI_LANGDLL_ALLLANGUAGES
!insertmacro MUI_LANGUAGE "English" ; first = default
!insertmacro MUI_LANGUAGE "Korean"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "Spanish"
!insertmacro MUI_LANGUAGE "Russian"
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "Czech"
!insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "Greek"
!insertmacro MUI_LANGUAGE "Arabic"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Italian"
!insertmacro MUI_LANGUAGE "Romanian"
!insertmacro MUI_LANGUAGE "Catalan"
!insertmacro MUI_LANGUAGE "Croatian"
!insertmacro MUI_LANGUAGE "Dutch"
!insertmacro MUI_LANGUAGE "Danish"
!insertmacro MUI_LANGUAGE "Hungarian"
!insertmacro MUI_LANGUAGE "Japanese"
!insertmacro MUI_LANGUAGE "Mongolian"
!insertmacro MUI_LANGUAGE "Norwegian"
!insertmacro MUI_LANGUAGE "PortugueseBR"
!insertmacro MUI_LANGUAGE "Serbian"
!insertmacro MUI_LANGUAGE "Slovak"
!insertmacro MUI_LANGUAGE "Slovenian"
!insertmacro MUI_LANGUAGE "Swedish"
!insertmacro MUI_LANGUAGE "Turkish"
!insertmacro MUI_LANGUAGE "Ukrainian"
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro MUI_RESERVEFILE_LANGDLL
; Language strings for all supported locales
!include lang_extra.nsh
!include lang_extra_fr.nsh
!include lang_extra_missing.nsh
; NOTE: The string "uninstFailed" must be defined in lang_extra.nsh and
; lang_extra_fr.nsh (and any other lang_extra_*.nsh) like so:
; LangString uninstFailed ${LANG_ENGLISH} "Uninstallation of the previous version failed.$\nPlease uninstall QElectroTech manually before continuing."
; LangString uninstFailed ${LANG_FRENCH} "La désinstallation de la version précédente a échoué.$\nVeuillez désinstaller QElectroTech manuellement avant de continuer."
;==============================================================================
; SECTIONS
;==============================================================================
SetOverwrite on
Section "Main Program"
SectionIn RO ; Read-only always installed
SetOutPath "$INSTDIR\bin\"
File "./files/bin/${SOFT_NAME}.exe"
SetOutPath "$INSTDIR"
File "./files/ChangeLog"
File "./files/CREDIT"
File "./files/ELEMENTS.LICENSE"
File "./files/LICENSE"
File "./files/qet_uninstall_file_associations.reg"
File "./files/README"
File "./files/register_filetypes.bat"
File "Lancer QET.bat"
SetOutPath "$INSTDIR"
File /r "./files/ico"
SectionEnd
;---------------------------
SetOverwrite on
SubSection "$(Elements)" SEC01
SetOverwrite on
Section "$(Electric)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/10_electric"
SectionEnd
SetOverwrite on
Section "$(Logic)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/20_logic"
SectionEnd
SetOverwrite on
Section "$(Hydraulic)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/30_hydraulic"
SectionEnd
SetOverwrite on
Section "$(Pneumatic)"
SetOutPath "$INSTDIR\elements"
File /r "./files/elements/50_pneumatic"
SectionEnd
;---------------------------------
SubSection "$(Energy)"
SetOverwrite on
Section "$(water)"
SetOutPath "$INSTDIR\elements\60_energy"
File /r "./files/elements/60_energy/11_water"
File /r "./files/elements/60_energy/"
SectionEnd
SetOverwrite on
Section "$(Refrigeration)"
SetOutPath "$INSTDIR\elements\60_energy"
File /r "./files/elements/60_energy/21_refrigeration"
File /r "./files/elements/60_energy/"
SectionEnd
SetOverwrite on
Section "$(Solar_thermal)"
SetOutPath "$INSTDIR\elements\60_energy"
File /r "./files/elements/60_energy/31_solar_thermal"
File /r "./files/elements/60_energy/"
SectionEnd
SubSectionEnd
SubSectionEnd
;-------------------------------
SetOverwrite on
Section "$(Lang)" SEC02
SetOutPath "$INSTDIR\lang"
File "./files/lang/*.qm"
SectionEnd
SetOverwrite on
Section "$(Titleblocks)" SEC03
SetOutPath "$INSTDIR"
File /r "./files/titleblocks"
SectionEnd
SetOverwrite on
Section "$(Examples)" SEC04
SetOutPath "$INSTDIR"
File /r "./files/examples"
SectionEnd
SetOverwrite on
Section "$(Fonts)" SEC05
SetOutPath "$INSTDIR"
File /r "./files/fonts"
SectionEnd
;--------------------------------
; Component descriptions
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC01} $(var1)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC02} $(var2)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC03} $(var3)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC04} $(var4)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC05} $(var5)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
; Hidden section: registry, shortcuts, file associations
Section ""
SetOutPath "$INSTDIR"
; NSIS 3 on 64-bit Windows: set 64-bit registry view BEFORE any WriteRegStr
; so keys land in HKLM\SOFTWARE (not the Wow6432Node redirect).
SetRegView 64
; Store installation folder
WriteRegStr HKCU "Software\${SOFT_NAME}" "" $INSTDIR
; Uninstall registry entries
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}" \
"DisplayName" "${SOFT_NAME} (remove only)"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}" \
"UninstallString" '"$INSTDIR\Uninstall.exe"'
; Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
; Build paths for icons and launch script
StrCpy $final_qet_exe "$INSTDIR\Lancer QET.bat"
StrCpy $final_project_ico "$INSTDIR\ico\application-x-qet-project.ico"
StrCpy $final_element_ico "$INSTDIR\ico\application-x-qet-element.ico"
StrCpy $final_titleblock_ico "$INSTDIR\ico\application-x-qet-titleblock.ico"
; File associations .qet
WriteRegStr HKEY_CLASSES_ROOT "Applications\qelectrotech.exe\shell\open\command" "" \
'"$final_qet_exe" "%1"'
WriteRegStr HKEY_CLASSES_ROOT ".qet" "" "qet_diagram_file"
WriteRegStr HKEY_CLASSES_ROOT "qet_diagram_file" "" "Diagram QET"
WriteRegDWORD HKEY_CLASSES_ROOT "qet_diagram_file" "EditFlags" 0x00000000
WriteRegDWORD HKEY_CLASSES_ROOT "qet_diagram_file" "BrowserFlags" 0x00000008
WriteRegStr HKEY_CLASSES_ROOT "qet_diagram_file\DefaultIcon" "" "$final_project_ico"
WriteRegStr HKEY_CLASSES_ROOT "qet_diagram_file\shell\open\command" "" '"$final_qet_exe" "%1"'
; File associations .elmt
WriteRegStr HKEY_CLASSES_ROOT ".elmt" "" "qet_element_file"
WriteRegStr HKEY_CLASSES_ROOT "qet_element_file" "" "Element QET"
WriteRegDWORD HKEY_CLASSES_ROOT "qet_element_file" "EditFlags" 0x00000000
WriteRegDWORD HKEY_CLASSES_ROOT "qet_element_file" "BrowserFlags" 0x00000008
WriteRegStr HKEY_CLASSES_ROOT "qet_element_file\DefaultIcon" "" "$final_element_ico"
WriteRegStr HKEY_CLASSES_ROOT "qet_element_file\shell\open\command" "" '"$final_qet_exe" "%1"'
; File associations .titleblock
WriteRegStr HKEY_CLASSES_ROOT ".titleblock" "" "qet_titleblock_file"
WriteRegStr HKEY_CLASSES_ROOT "qet_titleblock_file" "" "Titleblock QET"
WriteRegDWORD HKEY_CLASSES_ROOT "qet_titleblock_file" "EditFlags" 0x00000000
WriteRegDWORD HKEY_CLASSES_ROOT "qet_titleblock_file" "BrowserFlags" 0x00000008
WriteRegStr HKEY_CLASSES_ROOT "qet_titleblock_file\DefaultIcon" "" "$final_titleblock_ico"
WriteRegStr HKEY_CLASSES_ROOT "qet_titleblock_file\shell\open\command" "" '"$final_qet_exe" "%1"'
SetShellVarContext all ; apply shortcuts for all users
; Start Menu shortcuts
CreateDirectory "$SMPROGRAMS\${SOFT_NAME}"
CreateDirectory "$SMPROGRAMS\${SOFT_NAME}\Manual"
CreateDirectory "$SMPROGRAMS\${SOFT_NAME}\Upgrade"
CreateShortCut "$SMPROGRAMS\${SOFT_NAME}\QElectroTech.lnk" \
"$INSTDIR\Lancer QET.bat" 0 "$INSTDIR\ico\qelectrotech.ico"
CreateShortCut "$SMPROGRAMS\${SOFT_NAME}\Uninstall QElectroTech.lnk" \
"$INSTDIR\Uninstall.exe"
; Desktop shortcut
CreateShortCut "$DESKTOP\QElectroTech.lnk" \
"$INSTDIR\Lancer QET.bat" 0 "$INSTDIR\ico\qelectrotech.ico"
; Internet shortcuts
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Manual\Manual_English.url" \
"InternetShortcut" "URL" "https://download.qelectrotech.org/qet/manual_0.7/build/index.html"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Manual\Manual_Russian.url" \
"InternetShortcut" "URL" "https://download.qelectrotech.org/qet/joshua/html/QET_ru.html"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Upgrade\Download.url" \
"InternetShortcut" "URL" "https://download.qelectrotech.org/qet/builds/nightly/"
WriteINIStr "$SMPROGRAMS\${SOFT_NAME}\Donate.url" \
"InternetShortcut" "URL" "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZZHC9D7C3MDPC"
; Mark installed elements as read-only
${Locate} "$INSTDIR\elements\" "/L=FD /M=*.elmt" "LocateCallback"
IfErrors 0 +2
; MessageBox MB_OK "Error in Locate" ; uncomment for debugging
SectionEnd
;--------------------------------
; Locate callback sets FILE_ATTRIBUTE_READONLY on each .elmt file
Function LocateCallback
SetFileAttributes $R9 FILE_ATTRIBUTE_READONLY
Push $0
FunctionEnd
;==============================================================================
; INSTALLER FUNCTIONS
;==============================================================================
Function .onInit
; NSIS 3: SetRegView in .onInit ensures InstallDirRegKey reads the right hive
SetRegView 64
!insertmacro MUI_LANGDLL_DISPLAY
; Abort if not running on a 64-bit OS
${IfNot} ${RunningX64}
MessageBox MB_OK|MB_ICONSTOP $(wrongArch)
Abort
${EndIf}
; ----------------------------------------------------------------
; Auto-uninstall previous version before installing new one
; ----------------------------------------------------------------
ReadRegStr $R0 HKLM \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}" \
"UninstallString"
; No previous installation found → proceed normally
StrCmp $R0 "" done
; Also read the install dir of the previous version
ReadRegStr $R1 HKCU "Software\${SOFT_NAME}" ""
; Ask user whether to uninstall the existing version
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "$(installed)" IDOK uninst
Abort ; user clicked Cancel → stop the installer
uninst:
; Remove surrounding quotes from the UninstallString if present
; (some installers write: "C:\path\Uninstall.exe" — ExecWait needs clean path)
StrCpy $R2 $R0 1 ; first character
StrCmp $R2 '"' 0 unquoted
; Strip leading and trailing quote
StrCpy $R0 $R0 "" 1 ; remove leading "
StrLen $R3 $R0
IntOp $R3 $R3 - 1
StrCpy $R0 $R0 $R3 ; remove trailing "
unquoted:
; Run the uninstaller silently, keeping it in its own directory
; _?= prevents NSIS from copying the uninstaller to a temp folder,
; so it can delete itself and the whole $INSTDIR tree.
ClearErrors
${If} $R1 != ""
ExecWait '"$R0" /S _?=$R1' ; silent uninstall using saved install dir
${Else}
ExecWait '"$R0" /S' ; fallback if install dir unknown
${EndIf}
IfErrors uninstall_failed
; Verify the old installation is gone before continuing
${If} $R1 != ""
IfFileExists "$R1\${SOFT_NAME}.exe" uninstall_failed
IfFileExists "$R1\bin\${SOFT_NAME}.exe" uninstall_failed
${EndIf}
Goto done
uninstall_failed:
MessageBox MB_OK|MB_ICONSTOP "$(uninstFailed)"
Abort
done:
FunctionEnd
;==============================================================================
; UNINSTALLER SECTION
;==============================================================================
Section "Uninstall"
SetRegView 64 ; NSIS 3: required so we delete from the correct hive
SetShellVarContext all
; Remove Start Menu shortcuts
RMDir /r "$SMPROGRAMS\${SOFT_NAME}"
; Remove Desktop shortcut
Delete "$DESKTOP\QElectroTech.lnk"
; Remove application files
Delete "$INSTDIR\*.*"
RMDir /r "$INSTDIR"
; Remove installation registry keys
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${SOFT_NAME}"
DeleteRegKey /ifempty HKCU "Software\${SOFT_NAME}"
; Remove file associations registry keys
DeleteRegKey HKEY_CLASSES_ROOT "Applications\qelectrotech.exe"
DeleteRegKey HKEY_CLASSES_ROOT ".qet"
DeleteRegKey HKEY_CLASSES_ROOT "qet_diagram_file"
DeleteRegKey HKEY_CLASSES_ROOT ".elmt"
DeleteRegKey HKEY_CLASSES_ROOT "qet_element_file"
DeleteRegKey HKEY_CLASSES_ROOT ".titleblock"
DeleteRegKey HKEY_CLASSES_ROOT "qet_titleblock_file"
IfFileExists "$INSTDIR" 0 NoErrorMsg
; MessageBox MB_OK "Note: $INSTDIR could not be removed!"
NoErrorMsg:
SectionEnd
;==============================================================================
; UNINSTALLER FUNCTIONS
;==============================================================================
Function un.onInit
SetRegView 64 ; NSIS 3: match the view used during install
!insertmacro MUI_UNGETLANGUAGE
FunctionEnd
+191 -163
View File
@@ -10,6 +10,7 @@
LangString Refrigeration ${LANG_ENGLISH} "Refrigeration"
LangString Solar_thermal ${LANG_ENGLISH} "Solar_thermal"
LangString Lang ${LANG_ENGLISH} "Lang"
LangString Fonts ${LANG_ENGLISH} "Fonts"
LangString Titleblocks ${LANG_ENGLISH} "Titleblocks"
LangString Examples ${LANG_ENGLISH} "Examples"
LangString Check ${LANG_ENGLISH} "Check to start ${SOFT_NAME}"
@@ -17,6 +18,8 @@
LangString var2 ${LANG_ENGLISH} "languagues files"
LangString var3 ${LANG_ENGLISH} "Examples of cartridges"
LangString var4 ${LANG_ENGLISH} "Examples of diagrams"
LangString var5 ${LANG_ENGLISH} "Fonts"
LangString uninstFailed ${LANG_ENGLISH} "Uninstallation of the previous version failed.$\nPlease uninstall ${SOFT_NAME} manually before continuing."
LangString installed ${LANG_KOREAN} "${SOFT_NAME}이(가) 이미 설치되어 있습니다. $\n$\n이전 버전을 제거하려면 `OK`를, 업그레이드를 취소하려면 `Cancel`을 클릭하세요."
@@ -31,6 +34,7 @@
LangString Refrigeration ${LANG_KOREAN} "냉동"
LangString Solar_thermal ${LANG_KOREAN} "태양열"
LangString Lang ${LANG_KOREAN} "언어"
LangString Fonts ${LANG_KOREAN} "글꼴"
LangString Titleblocks ${LANG_KOREAN} "표제란"
LangString Examples ${LANG_KOREAN} "예제"
LangString Check ${LANG_KOREAN} "${SOFT_NAME} 실행"
@@ -38,6 +42,8 @@
LangString var2 ${LANG_KOREAN} "언어 파일"
LangString var3 ${LANG_KOREAN} "표제란 예제"
LangString var4 ${LANG_KOREAN} "도면 예제"
LangString var5 ${LANG_KOREAN} "글꼴"
LangString uninstFailed ${LANG_KOREAN} "이전 버전을 제거하지 못했습니다.$\n계속하기 전에 ${SOFT_NAME}을(를) 수동으로 제거해 주세요."
LangString installed ${LANG_POLISH} "${SOFT_NAME} jest już zainstalowany. $\n$\nKliknij `OK` aby odinstalować poprzednią wersję lub `Anuluj` aby przerwać aktualizację."
@@ -52,13 +58,16 @@
LangString Refrigeration ${LANG_POLISH} "Chłodnictwo"
LangString Solar_thermal ${LANG_POLISH} "Energia słoneczna"
LangString Lang ${LANG_POLISH} "Język"
LangString Fonts ${LANG_POLISH} "Czcionki"
LangString Titleblocks ${LANG_POLISH} "Tabliczki rysunkowe"
LangString Examples ${LANG_POLISH} "Przykłady"
LangString Check ${LANG_POLISH} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_POLISH} "Elements of the official collection"
LangString var2 ${LANG_POLISH} "languagues files"
LangString var3 ${LANG_POLISH} "Examples of cartridges"
LangString var4 ${LANG_POLISH} "Examples of diagrams"
LangString Check ${LANG_POLISH} "Zaznacz, aby uruchomić ${SOFT_NAME}"
LangString var1 ${LANG_POLISH} "Elementy oficjalnej kolekcji"
LangString var2 ${LANG_POLISH} "Pliki językowe"
LangString var3 ${LANG_POLISH} "Przykłady tabliczek rysunkowych"
LangString var4 ${LANG_POLISH} "Przykłady schematów"
LangString var5 ${LANG_POLISH} "Czcionki"
LangString uninstFailed ${LANG_POLISH} "Odinstalowanie poprzedniej wersji nie powiodło się.$\nPrzed kontynuowaniem odinstaluj ręcznie program ${SOFT_NAME}."
LangString installed ${LANG_GREEK} "${SOFT_NAME} είναι ήδη εγκατεστημένο. $\n$\nΠάτησε `OK` για αφαίρεση της προηγούμενης έκδοσης ή `Cancel` για ακύρωση της αναβάθμισης."
@@ -73,55 +82,64 @@
LangString Refrigeration ${LANG_GREEK} "Ψύξη"
LangString Solar_thermal ${LANG_GREEK} "Ηλιοθερμία"
LangString Lang ${LANG_GREEK} "Γλώσσα"
LangString Fonts ${LANG_GREEK} "Γραμματοσειρές"
LangString Titleblocks ${LANG_GREEK} "Πινακίδες"
LangString Examples ${LANG_GREEK} "Παραδείγματα"
LangString Check ${LANG_GREEK} "Επιλέξτε για εκκίνηση ${SOFT_NAME}"
LangString var1 ${LANG_GREEK} "Στοιχεία της επίσημης συλλογής"
LangString var2 ${LANG_GREEK} "Αρχεία γλωσσών"
LangString var3 ${LANG_GREEK} "Examples of cartridges"
LangString var3 ${LANG_GREEK} "Παραδείγματα πινακίδων"
LangString var4 ${LANG_GREEK} "Παραδείγματα διαγραμμάτων"
LangString var5 ${LANG_GREEK} "Γραμματοσειρές"
LangString uninstFailed ${LANG_GREEK} "Η απεγκατάσταση της προηγούμενης έκδοσης απέτυχε.$\nΠαρακαλώ απεγκαταστήστε χειροκίνητα το ${SOFT_NAME} πριν συνεχίσετε."
LangString installed ${LANG_CZECH} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_CZECH} "This distribution is for 64 bits computers only."
LangString Elements ${LANG_CZECH} "Elements"
LangString Electric ${LANG_CZECH} "Electric"
LangString Logic ${LANG_CZECH} "Logic"
LangString Hydraulic ${LANG_CZECH} "Hydraulic"
LangString Pneumatic ${LANG_CZECH} "Pneumatic"
LangString Energy ${LANG_CZECH} "Energy"
LangString water ${LANG_CZECH} "Water"
LangString Refrigeration ${LANG_CZECH} "Refrigeration"
LangString Solar_thermal ${LANG_CZECH} "Solar_thermal"
LangString Lang ${LANG_CZECH} "Lang"
LangString Titleblocks ${LANG_CZECH} "Titleblocks"
LangString Examples ${LANG_CZECH} "Examples"
LangString Check ${LANG_CZECH} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_CZECH} "Elements of the official collection"
LangString var2 ${LANG_CZECH} "languagues files"
LangString var3 ${LANG_CZECH} "Examples of cartridges"
LangString var4 ${LANG_CZECH} "Examples of diagrams"
LangString installed ${LANG_CZECH} "${SOFT_NAME} je již nainstalován. $\n$\nKlikněte na `OK` pro odebrání předchozí verze nebo na `Zrušit` pro zrušení tohoto upgradu."
LangString wrongArch ${LANG_CZECH} "Tato distribuce je určena pouze pro 64bitové počítače."
LangString Elements ${LANG_CZECH} "Prvky"
LangString Electric ${LANG_CZECH} "Elektrika"
LangString Logic ${LANG_CZECH} "Logika"
LangString Hydraulic ${LANG_CZECH} "Hydraulika"
LangString Pneumatic ${LANG_CZECH} "Pneumatika"
LangString Energy ${LANG_CZECH} "Energie"
LangString water ${LANG_CZECH} "Voda"
LangString Refrigeration ${LANG_CZECH} "Chlazení"
LangString Solar_thermal ${LANG_CZECH} "Solární_teplo"
LangString Lang ${LANG_CZECH} "Jazyk"
LangString Fonts ${LANG_CZECH} "Písma"
LangString Titleblocks ${LANG_CZECH} "Popisová pole"
LangString Examples ${LANG_CZECH} "Příklady"
LangString Check ${LANG_CZECH} "Zaškrtněte pro spuštění ${SOFT_NAME}"
LangString var1 ${LANG_CZECH} "Prvky oficiální kolekce"
LangString var2 ${LANG_CZECH} "Jazykové soubory"
LangString var3 ${LANG_CZECH} "Příklady popisových polí"
LangString var4 ${LANG_CZECH} "Příklady schémat"
LangString var5 ${LANG_CZECH} "Písma"
LangString uninstFailed ${LANG_CZECH} "Odinstalování předchozí verze se nezdařilo.$\nPřed pokračováním prosím odinstalujte ${SOFT_NAME} ručně."
LangString installed ${LANG_SPANISH} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_SPANISH} "This distribution is for 64 bits computers only."
LangString Elements ${LANG_SPANISH} "Elements"
LangString Electric ${LANG_SPANISH} "Electric"
LangString Logic ${LANG_SPANISH} "Logic"
LangString Hydraulic ${LANG_SPANISH} "Hydraulic"
LangString Pneumatic ${LANG_SPANISH} "Pneumatic"
LangString Energy ${LANG_SPANISH} "Energy"
LangString water ${LANG_SPANISH} "Water"
LangString Refrigeration ${LANG_SPANISH} "Refrigeration"
LangString Solar_thermal ${LANG_SPANISH} "Solar_thermal"
LangString Lang ${LANG_SPANISH} "Lang"
LangString Titleblocks ${LANG_SPANISH} "Titleblocks"
LangString Examples ${LANG_SPANISH} "Examples"
LangString Check ${LANG_SPANISH} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_SPANISH} "Elements of the official collection"
LangString var2 ${LANG_SPANISH} "languagues files"
LangString var3 ${LANG_SPANISH} "Examples of cartridges"
LangString var4 ${LANG_SPANISH} "Examples of diagrams"
LangString installed ${LANG_SPANISH} "${SOFT_NAME} ya está instalado. $\n$\nHaga clic en `Aceptar` para eliminar la versión anterior o en `Cancelar` para cancelar esta actualización."
LangString wrongArch ${LANG_SPANISH} "Esta distribución es solo para ordenadores de 64 bits."
LangString Elements ${LANG_SPANISH} "Elementos"
LangString Electric ${LANG_SPANISH} "Eléctrico"
LangString Logic ${LANG_SPANISH} "Lógica"
LangString Hydraulic ${LANG_SPANISH} "Hidráulica"
LangString Pneumatic ${LANG_SPANISH} "Neumática"
LangString Energy ${LANG_SPANISH} "Energía"
LangString water ${LANG_SPANISH} "Agua"
LangString Refrigeration ${LANG_SPANISH} "Refrigeración"
LangString Solar_thermal ${LANG_SPANISH} "Solar_térmico"
LangString Lang ${LANG_SPANISH} "Idioma"
LangString Fonts ${LANG_SPANISH} "Fuentes"
LangString Titleblocks ${LANG_SPANISH} "Cartelas"
LangString Examples ${LANG_SPANISH} "Ejemplos"
LangString Check ${LANG_SPANISH} "Marcar para iniciar ${SOFT_NAME}"
LangString var1 ${LANG_SPANISH} "Elementos de la colección oficial"
LangString var2 ${LANG_SPANISH} "Archivos de idioma"
LangString var3 ${LANG_SPANISH} "Ejemplos de cartelas"
LangString var4 ${LANG_SPANISH} "Ejemplos de esquemas"
LangString var5 ${LANG_SPANISH} "Fuentes"
LangString uninstFailed ${LANG_SPANISH} "La desinstalación de la versión anterior ha fallado.$\nPor favor, desinstale ${SOFT_NAME} manualmente antes de continuar."
LangString installed ${LANG_GERMAN} "${SOFT_NAME} ist bereits installiert. $\n$\nKlicken Sie auf `OK`, um die alte Version zu deinstallieren, oder auf `Abbrechen`, um das Upgrade abzubrechen."
@@ -136,6 +154,7 @@
LangString Refrigeration ${LANG_GERMAN} "Kältetechnik"
LangString Solar_thermal ${LANG_GERMAN} "Solar-Wärmetechnik"
LangString Lang ${LANG_GERMAN} "Sprachen"
LangString Fonts ${LANG_GERMAN} "Schriften"
LangString Titleblocks ${LANG_GERMAN} "Schriftfelder"
LangString Examples ${LANG_GERMAN} "Beispiele"
LangString Check ${LANG_GERMAN} "Ankreuzen zum Starten von ${SOFT_NAME}"
@@ -143,6 +162,8 @@
LangString var2 ${LANG_GERMAN} "Sprachdateien"
LangString var3 ${LANG_GERMAN} "Schriftfeld-Beispiele"
LangString var4 ${LANG_GERMAN} "Schaltplan-Beispiele"
LangString var5 ${LANG_GERMAN} "Schriften"
LangString uninstFailed ${LANG_GERMAN} "Die Deinstallation der vorherigen Version ist fehlgeschlagen.$\nBitte deinstallieren Sie ${SOFT_NAME} manuell, bevor Sie fortfahren."
LangString installed ${LANG_RUSSIAN} "${SOFT_NAME} уже установлен. $\n$\nДля удаления предыдущей версии нажмите `OK` или `Cancel` для отмены обновления."
@@ -157,6 +178,7 @@
LangString Refrigeration ${LANG_RUSSIAN} "Холодильная техника"
LangString Solar_thermal ${LANG_RUSSIAN} "Солнечная-тепловая"
LangString Lang ${LANG_RUSSIAN} "Язык"
LangString Fonts ${LANG_RUSSIAN} "Шрифты"
LangString Titleblocks ${LANG_RUSSIAN} "Штампы"
LangString Examples ${LANG_RUSSIAN} "Примеры"
LangString Check ${LANG_RUSSIAN} "Нажмите для запуска ${SOFT_NAME}"
@@ -164,48 +186,56 @@
LangString var2 ${LANG_RUSSIAN} "языковые файлы"
LangString var3 ${LANG_RUSSIAN} "Примеры штампов"
LangString var4 ${LANG_RUSSIAN} "Примеры схем"
LangString var5 ${LANG_RUSSIAN} "Шрифты"
LangString uninstFailed ${LANG_RUSSIAN} "Удаление предыдущей версии завершилось с ошибкой.$\nПожалуйста, удалите ${SOFT_NAME} вручную перед продолжением."
LangString installed ${LANG_ARABIC} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_ARABIC} "This distribution is for 64 bits computers only."
LangString Elements ${LANG_ARABIC} "Elements"
LangString Electric ${LANG_ARABIC} "Electric"
LangString Logic ${LANG_ARABIC} "Logic"
LangString Hydraulic ${LANG_ARABIC} "Hydraulic"
LangString Pneumatic ${LANG_ARABIC} "Pneumatic"
LangString Energy ${LANG_ARABIC} "Energy"
LangString water ${LANG_ARABIC} "Water"
LangString Refrigeration ${LANG_ARABIC} "Refrigeration"
LangString Solar_thermal ${LANG_ARABIC} "Solar_thermal"
LangString Lang ${LANG_ARABIC} "Lang"
LangString Titleblocks ${LANG_ARABIC} "Titleblocks"
LangString Examples ${LANG_ARABIC} "Examples"
LangString Check ${LANG_ARABIC} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_ARABIC} "Elements of the official collection"
LangString var2 ${LANG_ARABIC} "languagues files"
LangString var3 ${LANG_ARABIC} "Examples of cartridges"
LangString var4 ${LANG_ARABIC} "Examples of diagrams"
LangString installed ${LANG_ARABIC} "${SOFT_NAME} مثبَّت بالفعل. $\n$\nانقر على `موافق` لإزالة الإصدار السابق أو على `إلغاء` لإلغاء هذا التحديث."
LangString wrongArch ${LANG_ARABIC} "هذا التوزيع مخصص لأجهزة الكمبيوتر 64 بت فقط."
LangString Elements ${LANG_ARABIC} "العناصر"
LangString Electric ${LANG_ARABIC} "الكهرباء"
LangString Logic ${LANG_ARABIC} "المنطق"
LangString Hydraulic ${LANG_ARABIC} "الهيدروليك"
LangString Pneumatic ${LANG_ARABIC} "الهواء المضغوط"
LangString Energy ${LANG_ARABIC} "الطاقة"
LangString water ${LANG_ARABIC} "الماء"
LangString Refrigeration ${LANG_ARABIC} "التبريد"
LangString Solar_thermal ${LANG_ARABIC} "الطاقة_الشمسية_الحرارية"
LangString Lang ${LANG_ARABIC} "اللغة"
LangString Fonts ${LANG_ARABIC} "الخطوط"
LangString Titleblocks ${LANG_ARABIC} "كتل العنوان"
LangString Examples ${LANG_ARABIC} "أمثلة"
LangString Check ${LANG_ARABIC} "حدد لتشغيل ${SOFT_NAME}"
LangString var1 ${LANG_ARABIC} "عناصر المجموعة الرسمية"
LangString var2 ${LANG_ARABIC} "ملفات اللغة"
LangString var3 ${LANG_ARABIC} "أمثلة على كتل العنوان"
LangString var4 ${LANG_ARABIC} "أمثلة على المخططات"
LangString var5 ${LANG_ARABIC} "الخطوط"
LangString uninstFailed ${LANG_ARABIC} "فشل إلغاء تثبيت الإصدار السابق. يرجى إلغاء تثبيت ${SOFT_NAME} يدويًا قبل المتابعة."
LangString installed ${LANG_CATALAN} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_CATALAN} "This distribution is for 64 bits computers only."
LangString installed ${LANG_CATALAN} "${SOFT_NAME} ja està instal·lat. $\n$\nFeu clic a `D'acord` per eliminar la versió anterior o a `Cancel·la` per cancel·lar aquesta actualització."
LangString wrongArch ${LANG_CATALAN} "Aquesta distribució és només per a ordinadors de 64 bits."
LangString Elements ${LANG_CATALAN} "Elements"
LangString Electric ${LANG_CATALAN} "Electric"
LangString Logic ${LANG_CATALAN} "Logic"
LangString Hydraulic ${LANG_CATALAN} "Hydraulic"
LangString Pneumatic ${LANG_CATALAN} "Pneumatic"
LangString Energy ${LANG_CATALAN} "Energy"
LangString water ${LANG_CATALAN} "Water"
LangString Refrigeration ${LANG_CATALAN} "Refrigeration"
LangString Solar_thermal ${LANG_CATALAN} "Solar_thermal"
LangString Lang ${LANG_CATALAN} "Lang"
LangString Titleblocks ${LANG_CATALAN} "Titleblocks"
LangString Examples ${LANG_CATALAN} "Examples"
LangString Check ${LANG_CATALAN} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_CATALAN} "Elements of the official collection"
LangString var2 ${LANG_CATALAN} "languagues files"
LangString var3 ${LANG_CATALAN} "Examples of cartridges"
LangString var4 ${LANG_CATALAN} "Examples of diagrams"
LangString Electric ${LANG_CATALAN} "Elèctric"
LangString Logic ${LANG_CATALAN} "Lògica"
LangString Hydraulic ${LANG_CATALAN} "Hidràulica"
LangString Pneumatic ${LANG_CATALAN} "Pneumàtica"
LangString Energy ${LANG_CATALAN} "Energia"
LangString water ${LANG_CATALAN} "Aigua"
LangString Refrigeration ${LANG_CATALAN} "Refrigeració"
LangString Solar_thermal ${LANG_CATALAN} "Solar_tèrmic"
LangString Lang ${LANG_CATALAN} "Idioma"
LangString Fonts ${LANG_CATALAN} "Tipus de lletra"
LangString Titleblocks ${LANG_CATALAN} "Cartutxos"
LangString Examples ${LANG_CATALAN} "Exemples"
LangString Check ${LANG_CATALAN} "Marca per iniciar ${SOFT_NAME}"
LangString var1 ${LANG_CATALAN} "Elements de la col·lecció oficial"
LangString var2 ${LANG_CATALAN} "Fitxers d'idioma"
LangString var3 ${LANG_CATALAN} "Exemples de cartutxos"
LangString var4 ${LANG_CATALAN} "Exemples d'esquemes"
LangString var5 ${LANG_CATALAN} "Tipus de lletra"
LangString uninstFailed ${LANG_CATALAN} "La desinstal·lació de la versió anterior ha fallat.$\nSi us plau, desinstal·leu ${SOFT_NAME} manualment abans de continuar."
LangString installed ${LANG_ITALIAN} "${SOFT_NAME} &egrave; già installato. $\n$\nFare click su `OK` per rimuovere la versione precedente o su `Annulla` per annullare questo aggiornamento."
@@ -220,6 +250,7 @@
LangString Refrigeration ${LANG_ITALIAN} "Refrigerazione"
LangString Solar_thermal ${LANG_ITALIAN} "Solare_termico"
LangString Lang ${LANG_ITALIAN} "Lingua"
LangString Fonts ${LANG_ITALIAN} "Caratteri"
LangString Titleblocks ${LANG_ITALIAN} "Cartigli"
LangString Examples ${LANG_ITALIAN} "Esempi"
LangString Check ${LANG_ITALIAN} "Avvia ${SOFT_NAME}"
@@ -227,69 +258,80 @@
LangString var2 ${LANG_ITALIAN} "File della lingua"
LangString var3 ${LANG_ITALIAN} "Cartigli di esempio"
LangString var4 ${LANG_ITALIAN} "Schemi di esempio"
LangString var5 ${LANG_ITALIAN} "Caratteri"
LangString uninstFailed ${LANG_ITALIAN} "La disinstallazione della versione precedente non è riuscita.$\nSi prega di disinstallare ${SOFT_NAME} manualmente prima di continuare."
LangString installed ${LANG_PORTUGUESE} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_PORTUGUESE} "This distribution is for 64 bits computers only."
LangString Elements ${LANG_PORTUGUESE} "Elements"
LangString Electric ${LANG_PORTUGUESE} "Electric"
LangString Logic ${LANG_PORTUGUESE} "Logic"
LangString Hydraulic ${LANG_PORTUGUESE} "Hydraulic"
LangString Pneumatic ${LANG_PORTUGUESE} "Pneumatic"
LangString Energy ${LANG_PORTUGUESE} "Energy"
LangString water ${LANG_PORTUGUESE} "Water"
LangString Refrigeration ${LANG_PORTUGUESE} "Refrigeration"
LangString Solar_thermal ${LANG_PORTUGUESE} "Solar_thermal"
LangString Lang ${LANG_PORTUGUESE} "Lang"
LangString Titleblocks ${LANG_PORTUGUESE} "Titleblocks"
LangString Examples ${LANG_PORTUGUESE} "Examples"
LangString Check ${LANG_PORTUGUESE} "Avviare ${SOFT_NAME}"
LangString var1 ${LANG_PORTUGUESE} "Elements of the official collection"
LangString var2 ${LANG_PORTUGUESE} "languagues files"
LangString var3 ${LANG_PORTUGUESE} "Examples of cartridges"
LangString var4 ${LANG_PORTUGUESE} "Examples of diagrams"
LangString installed ${LANG_PORTUGUESE} "${SOFT_NAME} já está instalado. $\n$\nClique em `OK` para remover a versão anterior ou em `Cancelar` para cancelar esta atualização."
LangString wrongArch ${LANG_PORTUGUESE} "Esta distribuição é apenas para computadores de 64 bits."
LangString Elements ${LANG_PORTUGUESE} "Elementos"
LangString Electric ${LANG_PORTUGUESE} "Elétrica"
LangString Logic ${LANG_PORTUGUESE} "Lógica"
LangString Hydraulic ${LANG_PORTUGUESE} "Hidráulica"
LangString Pneumatic ${LANG_PORTUGUESE} "Pneumática"
LangString Energy ${LANG_PORTUGUESE} "Energia"
LangString water ${LANG_PORTUGUESE} "Água"
LangString Refrigeration ${LANG_PORTUGUESE} "Refrigeração"
LangString Solar_thermal ${LANG_PORTUGUESE} "Solar_térmico"
LangString Lang ${LANG_PORTUGUESE} "Idioma"
LangString Fonts ${LANG_PORTUGUESE} "Fontes"
LangString Titleblocks ${LANG_PORTUGUESE} "Legendas"
LangString Examples ${LANG_PORTUGUESE} "Exemplos"
LangString Check ${LANG_PORTUGUESE} "Marcar para iniciar ${SOFT_NAME}"
LangString var1 ${LANG_PORTUGUESE} "Elementos da coleção oficial"
LangString var2 ${LANG_PORTUGUESE} "Arquivos de idioma"
LangString var3 ${LANG_PORTUGUESE} "Exemplos de legendas"
LangString var4 ${LANG_PORTUGUESE} "Exemplos de esquemas"
LangString var5 ${LANG_PORTUGUESE} "Fontes"
LangString uninstFailed ${LANG_PORTUGUESE} "A desinstalação da versão anterior falhou.$\nPor favor, desinstale ${SOFT_NAME} manualmente antes de continuar."
LangString installed ${LANG_ROMANIAN} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_ROMANIAN} "This distribution is for 64 bits computers only."
LangString Elements ${LANG_ROMANIAN} "Elements"
LangString installed ${LANG_ROMANIAN} "${SOFT_NAME} este deja instalat. $\n$\nFaceți clic pe `OK` pentru a elimina versiunea anterioară sau pe `Anulare` pentru a anula această actualizare."
LangString wrongArch ${LANG_ROMANIAN} "Această distribuție este destinată numai computerelor pe 64 de biți."
LangString Elements ${LANG_ROMANIAN} "Elemente"
LangString Electric ${LANG_ROMANIAN} "Electric"
LangString Logic ${LANG_ROMANIAN} "Logic"
LangString Hydraulic ${LANG_ROMANIAN} "Hydraulic"
LangString Pneumatic ${LANG_ROMANIAN} "Pneumatic"
LangString Energy ${LANG_ROMANIAN} "Energy"
LangString water ${LANG_ROMANIAN} "Water"
LangString Refrigeration ${LANG_ROMANIAN} "Refrigeration"
LangString Solar_thermal ${LANG_ROMANIAN} "Solar_thermal"
LangString Lang ${LANG_ROMANIAN} "Lang"
LangString Titleblocks ${LANG_ROMANIAN} "Titleblocks"
LangString Examples ${LANG_ROMANIAN} "Examples"
LangString Check ${LANG_ROMANIAN} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_ROMANIAN} "Elements of the official collection"
LangString var2 ${LANG_ROMANIAN} "languagues files"
LangString var3 ${LANG_ROMANIAN} "Examples of cartridges"
LangString var4 ${LANG_ROMANIAN} "Examples of diagrams"
LangString Logic ${LANG_ROMANIAN} "Logică"
LangString Hydraulic ${LANG_ROMANIAN} "Hidraulică"
LangString Pneumatic ${LANG_ROMANIAN} "Pneumatică"
LangString Energy ${LANG_ROMANIAN} "Energie"
LangString water ${LANG_ROMANIAN} "Apă"
LangString Refrigeration ${LANG_ROMANIAN} "Refrigerare"
LangString Solar_thermal ${LANG_ROMANIAN} "Solar_termic"
LangString Lang ${LANG_ROMANIAN} "Limbă"
LangString Fonts ${LANG_ROMANIAN} "Fonturi"
LangString Titleblocks ${LANG_ROMANIAN} "Cartușe"
LangString Examples ${LANG_ROMANIAN} "Exemple"
LangString Check ${LANG_ROMANIAN} "Bifați pentru a porni ${SOFT_NAME}"
LangString var1 ${LANG_ROMANIAN} "Elemente din colecția oficială"
LangString var2 ${LANG_ROMANIAN} "Fișiere de limbă"
LangString var3 ${LANG_ROMANIAN} "Exemple de cartușe"
LangString var4 ${LANG_ROMANIAN} "Exemple de scheme"
LangString var5 ${LANG_ROMANIAN} "Fonturi"
LangString uninstFailed ${LANG_ROMANIAN} "Dezinstalarea versiunii anterioare a eșuat.$\nVă rugăm să dezinstalați ${SOFT_NAME} manual înainte de a continua."
LangString installed ${LANG_CROATIAN} "${SOFT_NAME} is already installed. $\n$\nClick `OK` to remove the previous version or `Cancel` to cancel this upgrade."
LangString wrongArch ${LANG_CROATIAN} "This distribution is for 64 bits computers only."
LangString Elements ${LANG_CROATIAN} "Elements"
LangString Electric ${LANG_CROATIAN} "Electric"
LangString Logic ${LANG_CROATIAN} "Logic"
LangString Hydraulic ${LANG_CROATIAN} "Hydraulic"
LangString Pneumatic ${LANG_CROATIAN} "Pneumatic"
LangString Energy ${LANG_CROATIAN} "Energy"
LangString water ${LANG_CROATIAN} "Water"
LangString Refrigeration ${LANG_CROATIAN} "Refrigeration"
LangString Solar_thermal ${LANG_CROATIAN} "Solar_thermal"
LangString Lang ${LANG_CROATIAN} "Lang"
LangString Titleblocks ${LANG_CROATIAN} "Titleblocks"
LangString Examples ${LANG_CROATIAN} "Examples"
LangString Check ${LANG_CROATIAN} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_CROATIAN} "Elements of the official collection"
LangString var2 ${LANG_CROATIAN} "languagues files"
LangString var3 ${LANG_CROATIAN} "Examples of cartridges"
LangString var4 ${LANG_CROATIAN} "Examples of diagrams"
LangString installed ${LANG_CROATIAN} "${SOFT_NAME} je već instaliran. $\n$\nKliknite `U redu` za uklanjanje prethodne verzije ili `Odustani` za odustajanje od nadogradnje."
LangString wrongArch ${LANG_CROATIAN} "Ova distribucija namijenjena je samo za 64-bitna računala."
LangString Elements ${LANG_CROATIAN} "Elementi"
LangString Electric ${LANG_CROATIAN} "Elektrika"
LangString Logic ${LANG_CROATIAN} "Logika"
LangString Hydraulic ${LANG_CROATIAN} "Hidraulika"
LangString Pneumatic ${LANG_CROATIAN} "Pneumatika"
LangString Energy ${LANG_CROATIAN} "Energija"
LangString water ${LANG_CROATIAN} "Voda"
LangString Refrigeration ${LANG_CROATIAN} "Hlađenje"
LangString Solar_thermal ${LANG_CROATIAN} "Solarno_toplinsko"
LangString Lang ${LANG_CROATIAN} "Jezik"
LangString Fonts ${LANG_CROATIAN} "Fontovi"
LangString Titleblocks ${LANG_CROATIAN} "Zaglavlja"
LangString Examples ${LANG_CROATIAN} "Primjeri"
LangString Check ${LANG_CROATIAN} "Označite za pokretanje ${SOFT_NAME}"
LangString var1 ${LANG_CROATIAN} "Elementi službene zbirke"
LangString var2 ${LANG_CROATIAN} "Jezične datoteke"
LangString var3 ${LANG_CROATIAN} "Primjeri zaglavlja"
LangString var4 ${LANG_CROATIAN} "Primjeri shema"
LangString var5 ${LANG_CROATIAN} "Fontovi"
LangString uninstFailed ${LANG_CROATIAN} "Deinstalacija prethodne verzije nije uspjela.$\nMolimo deinstalirajte ${SOFT_NAME} ručno prije nastavka."
LangString installed ${LANG_DUTCH} "${SOFT_NAME} is al geinstalleerd. $\n$\nklik `OK` om vorige versie te verwijderen of `annuleer` om deze upgrade te annuleren."
@@ -304,34 +346,16 @@
LangString Refrigeration ${LANG_DUTCH} "Koelinstallaties"
LangString Solar_thermal ${LANG_DUTCH} "Zonne_warmte"
LangString Lang ${LANG_DUTCH} "Taal"
LangString Fonts ${LANG_DUTCH} "Lettertypen"
LangString Titleblocks ${LANG_DUTCH} "Titelblok"
LangString Examples ${LANG_DUTCH} "Voorbeelden"
LangString Check ${LANG_DUTCH} "Check to start ${SOFT_NAME}"
LangString Check ${LANG_DUTCH} "Check to start ${SOFT_NAME}"
LangString var1 ${LANG_DUTCH} "Elements of the official collection"
LangString var2 ${LANG_DUTCH} "languagues files"
LangString var3 ${LANG_DUTCH} "Examples of cartridges"
LangString var4 ${LANG_DUTCH} "Examples of diagrams"
LangString installed ${LANG_DUTCH_BELGIUM} "${SOFT_NAME} is reeds geinstallerd. $\n$\nKlik`OK` om vorige versie te verwijderen of `Afbreken` om de upgrade niet uit te voeren."
LangString wrongArch ${LANG_DUTCH_BELGIUM} "Deze distributie werkt enkel op 64 bits computers."
LangString Elements ${LANG_DUTCH_BELGIUM} "Elementen"
LangString Electric ${LANG_DUTCH_BELGIUM} "Electrisch"
LangString Logic ${LANG_DUTCH_BELGIUM} "Logica"
LangString Hydraulic ${LANG_DUTCH_BELGIUM} "Hydraulisch"
LangString Pneumatic ${LANG_DUTCH_BELGIUM} "Pneumatisch"
LangString Energy ${LANG_DUTCH_BELGIUM} "Energie"
LangString water ${LANG_DUTCH_BELGIUM} "Water"
LangString Refrigeration ${LANG_DUTCH_BELGIUM} "Klimatisatie"
LangString Solar_thermal ${LANG_DUTCH_BELGIUM} "Termisch & zonlicht"
LangString Lang ${LANG_DUTCH_BELGIUM} "Taal"
LangString Titleblocks ${LANG_DUTCH_BELGIUM} "Titelhoek"
LangString Examples ${LANG_DUTCH_BELGIUM} "Voorbeelden"
LangString Check ${LANG_DUTCH_BELGIUM} "Controleer om te beginnen ${SOFT_NAME}"
LangString var1 ${LANG_DUTCH_BELGIUM} "Symbolen van de officielen verzameling"
LangString var2 ${LANG_DUTCH_BELGIUM} "taal bestanden"
LangString var3 ${LANG_DUTCH_BELGIUM} "Voorbeel titelhoeken"
LangString var4 ${LANG_DUTCH_BELGIUM} "Voorbeeld schema's"
LangString Check ${LANG_DUTCH} "Aanvinken om ${SOFT_NAME} te starten"
LangString var1 ${LANG_DUTCH} "Elementen van de officiële verzameling"
LangString var2 ${LANG_DUTCH} "Taalbestanden"
LangString var3 ${LANG_DUTCH} "Voorbeelden van titelblokken"
LangString var4 ${LANG_DUTCH} "Voorbeelden van schema's"
LangString var5 ${LANG_DUTCH} "Lettertypen"
LangString uninstFailed ${LANG_DUTCH} "Het verwijderen van de vorige versie is mislukt.$\nVerwijder ${SOFT_NAME} handmatig voordat u verdergaat."
LangString installed ${LANG_DANISH} "${SOFT_NAME} er allerede installeret. $\n$\nKlik `Ok` for at fjerne foregående version eller `Annuller` for at annullere opgraderingen."
@@ -346,6 +370,7 @@
LangString Refrigeration ${LANG_DANISH} "Køle teknik"
LangString Solar_thermal ${LANG_DANISH} "Sol & varme teknik"
LangString Lang ${LANG_DANISH} "Sprog"
LangString Fonts ${LANG_DANISH} "Skrifttyper"
LangString Titleblocks ${LANG_DANISH} "Titel blokke"
LangString Examples ${LANG_DANISH} "Eksempler"
LangString Check ${LANG_DANISH} "Vælg for at starte ${SOFT_NAME}"
@@ -353,5 +378,8 @@
LangString var2 ${LANG_DANISH} "Sprog filer"
LangString var3 ${LANG_DANISH} "Titel blokke eksempler"
LangString var4 ${LANG_DANISH} "Diagram eksempler"
LangString var5 ${LANG_DANISH} "Skrifttyper"
LangString uninstFailed ${LANG_DANISH} "Afinstallation af den tidligere version mislykkedes.$\nAfinstaller venligst ${SOFT_NAME} manuelt, inden du fortsætter."
+7 -4
View File
@@ -1,6 +1,6 @@
LangString wrongArch ${LANG_FRENCH} "Ce programme est pour Windows 64 bits seulement."
LangString installed ${LANG_FRENCH} "${SOFT_NAME} est déja installé. $\n$\nCliquer sur `OK` pour désinstaller l'ancienne version `Annuler` pour annuler cet upgrade."
LangString Elements ${LANG_FRENCH} "Eléments"
LangString installed ${LANG_FRENCH} "${SOFT_NAME} est déja installé. $\n$\nCliquer sur `OK` pour désinstaller l'ancienne version `Annuler` pour annuler cet upgrade."
LangString Elements ${LANG_FRENCH} "Eléments"
LangString Electric ${LANG_FRENCH} "Electrique"
LangString Logic ${LANG_FRENCH} "Logique"
LangString Hydraulic ${LANG_FRENCH} "Hydraulique"
@@ -10,10 +10,13 @@
LangString Refrigeration ${LANG_FRENCH} "Climatisation"
LangString Solar_thermal ${LANG_FRENCH} "Thermique & solaire"
LangString Lang ${LANG_FRENCH} "Langues"
LangString Fonts ${LANG_FRENCH} "Polices"
LangString Titleblocks ${LANG_FRENCH} "Cartouches"
LangString Examples ${LANG_FRENCH} "Exemples"
LangString Check ${LANG_FRENCH} "Cocher pour lancer ${SOFT_NAME}"
LangString var1 ${LANG_FRENCH} "Eléments de la collection officielle"
LangString var1 ${LANG_FRENCH} "Eléments de la collection officielle"
LangString var2 ${LANG_FRENCH} "Fichiers de langues"
LangString var3 ${LANG_FRENCH} "Exemples de cartouches"
LangString var4 ${LANG_FRENCH} "Exemples de schémas"
LangString var4 ${LANG_FRENCH} "Exemples de schémas"
LangString var5 ${LANG_FRENCH} "Polices"
LangString uninstFailed ${LANG_FRENCH} "La désinstallation de la version précédente a échoué.$\nVeuillez désinstaller ${SOFT_NAME} manuellement avant de continuer."
+335
View File
@@ -0,0 +1,335 @@
; Missing language translations for QElectroTech installer
; Languages added: hu, ja, mn, nb, nl_BE, nl_NL, pt_BR, rs/sr, sk, sl, sv, tr, uk, zh
; ----------------------------------------------------------------
; Hungarian (LANG_HUNGARIAN)
; ----------------------------------------------------------------
LangString installed ${LANG_HUNGARIAN} "${SOFT_NAME} már telepítve van. $\n$\nKattintson az `OK` gombra az előző verzió eltávolításához, vagy a `Mégse` gombra a frissítés megszakításához."
LangString wrongArch ${LANG_HUNGARIAN} "Ez a terjesztés csak 64 bites számítógépekre való."
LangString Elements ${LANG_HUNGARIAN} "Elemek"
LangString Electric ${LANG_HUNGARIAN} "Elektromos"
LangString Logic ${LANG_HUNGARIAN} "Logika"
LangString Hydraulic ${LANG_HUNGARIAN} "Hidraulika"
LangString Pneumatic ${LANG_HUNGARIAN} "Pneumatika"
LangString Energy ${LANG_HUNGARIAN} "Energia"
LangString water ${LANG_HUNGARIAN} "Víz"
LangString Refrigeration ${LANG_HUNGARIAN} "Hűtés"
LangString Solar_thermal ${LANG_HUNGARIAN} "Nap_hőenergia"
LangString Lang ${LANG_HUNGARIAN} "Nyelv"
LangString Fonts ${LANG_HUNGARIAN} "Betűtípusok"
LangString Titleblocks ${LANG_HUNGARIAN} "Rajzfejlécek"
LangString Examples ${LANG_HUNGARIAN} "Példák"
LangString Check ${LANG_HUNGARIAN} "Jelölje be a ${SOFT_NAME} indításához"
LangString var1 ${LANG_HUNGARIAN} "A hivatalos gyűjtemény elemei"
LangString var2 ${LANG_HUNGARIAN} "Nyelvfájlok"
LangString var3 ${LANG_HUNGARIAN} "Rajzfejléc-példák"
LangString var4 ${LANG_HUNGARIAN} "Kapcsolási rajz példák"
LangString var5 ${LANG_HUNGARIAN} "Betűtípusok"
LangString uninstFailed ${LANG_HUNGARIAN} "Az előző verzió eltávolítása nem sikerült.$\nKérjük, távolítsa el manuálisan a ${SOFT_NAME} programot, mielőtt folytatná."
; ----------------------------------------------------------------
; Japanese (LANG_JAPANESE)
; ----------------------------------------------------------------
LangString installed ${LANG_JAPANESE} "${SOFT_NAME} はすでにインストールされています。$\n$\n前のバージョンを削除するには `OK` をクリックし、このアップグレードをキャンセルするには `キャンセル` をクリックしてください。"
LangString wrongArch ${LANG_JAPANESE} "この配布パッケージは64ビットコンピュータ専用です。"
LangString Elements ${LANG_JAPANESE} "部品"
LangString Electric ${LANG_JAPANESE} "電気"
LangString Logic ${LANG_JAPANESE} "論理"
LangString Hydraulic ${LANG_JAPANESE} "油圧"
LangString Pneumatic ${LANG_JAPANESE} "空圧"
LangString Energy ${LANG_JAPANESE} "エネルギー"
LangString water ${LANG_JAPANESE} ""
LangString Refrigeration ${LANG_JAPANESE} "冷凍"
LangString Solar_thermal ${LANG_JAPANESE} "太陽熱"
LangString Lang ${LANG_JAPANESE} "言語"
LangString Fonts ${LANG_JAPANESE} "フォント"
LangString Titleblocks ${LANG_JAPANESE} "表題欄"
LangString Examples ${LANG_JAPANESE} ""
LangString Check ${LANG_JAPANESE} "${SOFT_NAME} を起動するにはチェックを入れてください"
LangString var1 ${LANG_JAPANESE} "公式コレクションの部品"
LangString var2 ${LANG_JAPANESE} "言語ファイル"
LangString var3 ${LANG_JAPANESE} "表題欄の例"
LangString var4 ${LANG_JAPANESE} "回路図の例"
LangString var5 ${LANG_JAPANESE} "フォント"
LangString uninstFailed ${LANG_JAPANESE} "前のバージョンのアンインストールに失敗しました。$\n続行する前に、${SOFT_NAME} を手動でアンインストールしてください。"
; ----------------------------------------------------------------
; Mongolian (LANG_MONGOLIAN)
; ----------------------------------------------------------------
LangString installed ${LANG_MONGOLIAN} "${SOFT_NAME} аль хэдийн суулгасан байна. $\n$\nӨмнөх хувилбарыг устгахын тулд `OK` дарна уу эсвэл энэ шинэчлэлтийг цуцлахын тулд `Цуцлах` дарна уу."
LangString wrongArch ${LANG_MONGOLIAN} "Энэ тарилга нь зөвхөн 64 битийн компьютерт зориулагдсан."
LangString Elements ${LANG_MONGOLIAN} "Элементүүд"
LangString Electric ${LANG_MONGOLIAN} "Цахилгаан"
LangString Logic ${LANG_MONGOLIAN} "Логик"
LangString Hydraulic ${LANG_MONGOLIAN} "Гидравлик"
LangString Pneumatic ${LANG_MONGOLIAN} "Пневматик"
LangString Energy ${LANG_MONGOLIAN} "Эрчим хүч"
LangString water ${LANG_MONGOLIAN} "Ус"
LangString Refrigeration ${LANG_MONGOLIAN} "Хөргөлт"
LangString Solar_thermal ${LANG_MONGOLIAN} "Нарны_дулаан"
LangString Lang ${LANG_MONGOLIAN} "Хэл"
LangString Fonts ${LANG_MONGOLIAN} "Фонт"
LangString Titleblocks ${LANG_MONGOLIAN} "Гарчгийн блокууд"
LangString Examples ${LANG_MONGOLIAN} "Жишээнүүд"
LangString Check ${LANG_MONGOLIAN} "${SOFT_NAME} эхлүүлэхийн тулд тэмдэглэнэ үү"
LangString var1 ${LANG_MONGOLIAN} "Албан ёсны цуглуулгын элементүүд"
LangString var2 ${LANG_MONGOLIAN} "Хэлний файлууд"
LangString var3 ${LANG_MONGOLIAN} "Гарчгийн блокын жишээнүүд"
LangString var4 ${LANG_MONGOLIAN} "Схемийн жишээнүүд"
LangString var5 ${LANG_MONGOLIAN} "Фонт"
LangString uninstFailed ${LANG_MONGOLIAN} "Өмнөх хувилбарыг устгаж чадсангүй.$\nҮргэлжлүүлэхийн өмнө ${SOFT_NAME}-г гараар устгана уу."
; ----------------------------------------------------------------
; Norwegian Bokmål (LANG_NORWEGIAN)
; ----------------------------------------------------------------
LangString installed ${LANG_NORWEGIAN} "${SOFT_NAME} er allerede installert. $\n$\nKlikk `OK` for å fjerne forrige versjon, eller `Avbryt` for å avbryte denne oppgraderingen."
LangString wrongArch ${LANG_NORWEGIAN} "Denne distribusjonen er kun for 64-biters datamaskiner."
LangString Elements ${LANG_NORWEGIAN} "Elementer"
LangString Electric ${LANG_NORWEGIAN} "Elektrisk"
LangString Logic ${LANG_NORWEGIAN} "Logikk"
LangString Hydraulic ${LANG_NORWEGIAN} "Hydraulikk"
LangString Pneumatic ${LANG_NORWEGIAN} "Pneumatikk"
LangString Energy ${LANG_NORWEGIAN} "Energi"
LangString water ${LANG_NORWEGIAN} "Vann"
LangString Refrigeration ${LANG_NORWEGIAN} "Kjøling"
LangString Solar_thermal ${LANG_NORWEGIAN} "Solvarme"
LangString Lang ${LANG_NORWEGIAN} "Språk"
LangString Fonts ${LANG_NORWEGIAN} "Skrifttyper"
LangString Titleblocks ${LANG_NORWEGIAN} "Titelblokker"
LangString Examples ${LANG_NORWEGIAN} "Eksempler"
LangString Check ${LANG_NORWEGIAN} "Kryss av for å starte ${SOFT_NAME}"
LangString var1 ${LANG_NORWEGIAN} "Elementer fra den offisielle samlingen"
LangString var2 ${LANG_NORWEGIAN} "Språkfiler"
LangString var3 ${LANG_NORWEGIAN} "Eksempler på titelblokker"
LangString var4 ${LANG_NORWEGIAN} "Eksempler på skjemaer"
LangString var5 ${LANG_NORWEGIAN} "Skrifttyper"
LangString uninstFailed ${LANG_NORWEGIAN} "Avinstallasjon av forrige versjon mislyktes.$\nVennligst avinstaller ${SOFT_NAME} manuelt før du fortsetter."
; ----------------------------------------------------------------
; Dutch Belgium (LANG_DUTCH / nl_BE — same LANG_DUTCH constant, Belgian variant)
; Note: NSIS uses a single LANG_DUTCH constant for both nl_BE and nl_NL.
; If your build distinguishes them via a custom constant, replace accordingly.
; The block below is already covered by LANG_DUTCH in lang_extra.nsh.
; Included here for completeness / override if needed.
; ----------------------------------------------------------------
; (nl_BE uses the same LANG_DUTCH strings already defined in lang_extra.nsh)
; ----------------------------------------------------------------
; Portuguese Brazil (LANG_PORTUGUESEBR)
; ----------------------------------------------------------------
LangString installed ${LANG_PORTUGUESEBR} "${SOFT_NAME} já está instalado. $\n$\nClique em `OK` para remover a versão anterior ou em `Cancelar` para cancelar esta atualização."
LangString wrongArch ${LANG_PORTUGUESEBR} "Esta distribuição é apenas para computadores de 64 bits."
LangString Elements ${LANG_PORTUGUESEBR} "Elementos"
LangString Electric ${LANG_PORTUGUESEBR} "Elétrico"
LangString Logic ${LANG_PORTUGUESEBR} "Lógica"
LangString Hydraulic ${LANG_PORTUGUESEBR} "Hidráulica"
LangString Pneumatic ${LANG_PORTUGUESEBR} "Pneumática"
LangString Energy ${LANG_PORTUGUESEBR} "Energia"
LangString water ${LANG_PORTUGUESEBR} "Água"
LangString Refrigeration ${LANG_PORTUGUESEBR} "Refrigeração"
LangString Solar_thermal ${LANG_PORTUGUESEBR} "Solar_térmico"
LangString Lang ${LANG_PORTUGUESEBR} "Idioma"
LangString Fonts ${LANG_PORTUGUESEBR} "Fontes"
LangString Titleblocks ${LANG_PORTUGUESEBR} "Legendas"
LangString Examples ${LANG_PORTUGUESEBR} "Exemplos"
LangString Check ${LANG_PORTUGUESEBR} "Marcar para iniciar ${SOFT_NAME}"
LangString var1 ${LANG_PORTUGUESEBR} "Elementos da coleção oficial"
LangString var2 ${LANG_PORTUGUESEBR} "Arquivos de idioma"
LangString var3 ${LANG_PORTUGUESEBR} "Exemplos de legendas"
LangString var4 ${LANG_PORTUGUESEBR} "Exemplos de esquemas"
LangString var5 ${LANG_PORTUGUESEBR} "Fontes"
LangString uninstFailed ${LANG_PORTUGUESEBR} "A desinstalação da versão anterior falhou.$\nPor favor, desinstale ${SOFT_NAME} manualmente antes de continuar."
; ----------------------------------------------------------------
; Serbian (LANG_SERBIAN) — covers rs/sr
; ----------------------------------------------------------------
LangString installed ${LANG_SERBIAN} "${SOFT_NAME} је већ инсталиран. $\n$\nКликните `OK` да уклоните претходну верзију или `Откажи` да откажете надоградњу."
LangString wrongArch ${LANG_SERBIAN} "Ова дистрибуција је намењена само за 64-битна рачунала."
LangString Elements ${LANG_SERBIAN} "Елементи"
LangString Electric ${LANG_SERBIAN} "Електрика"
LangString Logic ${LANG_SERBIAN} "Логика"
LangString Hydraulic ${LANG_SERBIAN} "Хидраулика"
LangString Pneumatic ${LANG_SERBIAN} "Пнеуматика"
LangString Energy ${LANG_SERBIAN} "Енергија"
LangString water ${LANG_SERBIAN} "Вода"
LangString Refrigeration ${LANG_SERBIAN} "Хлађење"
LangString Solar_thermal ${LANG_SERBIAN} "Соларно_топлотно"
LangString Lang ${LANG_SERBIAN} "Језик"
LangString Fonts ${LANG_SERBIAN} "Фонтови"
LangString Titleblocks ${LANG_SERBIAN} "Заглавља"
LangString Examples ${LANG_SERBIAN} "Примери"
LangString Check ${LANG_SERBIAN} "Означите за покретање ${SOFT_NAME}"
LangString var1 ${LANG_SERBIAN} "Елементи службене збирке"
LangString var2 ${LANG_SERBIAN} "Језичке датотеке"
LangString var3 ${LANG_SERBIAN} "Примери заглавља"
LangString var4 ${LANG_SERBIAN} "Примери шема"
LangString var5 ${LANG_SERBIAN} "Фонтови"
LangString uninstFailed ${LANG_SERBIAN} "Деинсталација претходне верзије није успела.$\nМолимо деинсталирајте ${SOFT_NAME} ручно пре наставка."
; ----------------------------------------------------------------
; Slovak (LANG_SLOVAK)
; ----------------------------------------------------------------
LangString installed ${LANG_SLOVAK} "${SOFT_NAME} je už nainštalovaný. $\n$\nKliknutím na `OK` odstráňte predchádzajúcu verziu alebo kliknite na `Zrušiť` pre zrušenie tohto upgradu."
LangString wrongArch ${LANG_SLOVAK} "Táto distribúcia je určená len pre 64-bitové počítače."
LangString Elements ${LANG_SLOVAK} "Prvky"
LangString Electric ${LANG_SLOVAK} "Elektrika"
LangString Logic ${LANG_SLOVAK} "Logika"
LangString Hydraulic ${LANG_SLOVAK} "Hydraulika"
LangString Pneumatic ${LANG_SLOVAK} "Pneumatika"
LangString Energy ${LANG_SLOVAK} "Energia"
LangString water ${LANG_SLOVAK} "Voda"
LangString Refrigeration ${LANG_SLOVAK} "Chladenie"
LangString Solar_thermal ${LANG_SLOVAK} "Solarne_teplo"
LangString Lang ${LANG_SLOVAK} "Jazyk"
LangString Fonts ${LANG_SLOVAK} "Písma"
LangString Titleblocks ${LANG_SLOVAK} "Popisové polia"
LangString Examples ${LANG_SLOVAK} "Príklady"
LangString Check ${LANG_SLOVAK} "Začiarknite pre spustenie ${SOFT_NAME}"
LangString var1 ${LANG_SLOVAK} "Prvky oficiálnej zbierky"
LangString var2 ${LANG_SLOVAK} "Jazykové súbory"
LangString var3 ${LANG_SLOVAK} "Príklady popisových polí"
LangString var4 ${LANG_SLOVAK} "Príklady schém"
LangString var5 ${LANG_SLOVAK} "Písma"
LangString uninstFailed ${LANG_SLOVAK} "Odinštalovanie predchádzajúcej verzie zlyhalo.$\nPred pokračovaním odinštalujte ${SOFT_NAME} ručne."
; ----------------------------------------------------------------
; Slovenian (LANG_SLOVENIAN)
; ----------------------------------------------------------------
LangString installed ${LANG_SLOVENIAN} "${SOFT_NAME} je že nameščen. $\n$\nKliknite `OK` za odstranitev prejšnje različice ali `Prekliči` za preklic te nadgradnje."
LangString wrongArch ${LANG_SLOVENIAN} "Ta distribucija je namenjena samo za 64-bitne računalnike."
LangString Elements ${LANG_SLOVENIAN} "Elementi"
LangString Electric ${LANG_SLOVENIAN} "Elektrika"
LangString Logic ${LANG_SLOVENIAN} "Logika"
LangString Hydraulic ${LANG_SLOVENIAN} "Hidravlika"
LangString Pneumatic ${LANG_SLOVENIAN} "Pnevmatika"
LangString Energy ${LANG_SLOVENIAN} "Energija"
LangString water ${LANG_SLOVENIAN} "Voda"
LangString Refrigeration ${LANG_SLOVENIAN} "Hlajenje"
LangString Solar_thermal ${LANG_SLOVENIAN} "Solarno_toplotno"
LangString Lang ${LANG_SLOVENIAN} "Jezik"
LangString Fonts ${LANG_SLOVENIAN} "Pisave"
LangString Titleblocks ${LANG_SLOVENIAN} "Glave risb"
LangString Examples ${LANG_SLOVENIAN} "Primeri"
LangString Check ${LANG_SLOVENIAN} "Označite za zagon ${SOFT_NAME}"
LangString var1 ${LANG_SLOVENIAN} "Elementi uradne zbirke"
LangString var2 ${LANG_SLOVENIAN} "Jezikovne datoteke"
LangString var3 ${LANG_SLOVENIAN} "Primeri glav risb"
LangString var4 ${LANG_SLOVENIAN} "Primeri shem"
LangString var5 ${LANG_SLOVENIAN} "Pisave"
LangString uninstFailed ${LANG_SLOVENIAN} "Odstranitev prejšnje različice ni uspela.$\nPred nadaljevanjem ročno odstranite ${SOFT_NAME}."
; ----------------------------------------------------------------
; Swedish (LANG_SWEDISH)
; ----------------------------------------------------------------
LangString installed ${LANG_SWEDISH} "${SOFT_NAME} är redan installerat. $\n$\nKlicka på `OK` för att ta bort den tidigare versionen eller `Avbryt` för att avbryta uppgraderingen."
LangString wrongArch ${LANG_SWEDISH} "Den här distributionen är endast för 64-bitars datorer."
LangString Elements ${LANG_SWEDISH} "Element"
LangString Electric ${LANG_SWEDISH} "Elektrisk"
LangString Logic ${LANG_SWEDISH} "Logik"
LangString Hydraulic ${LANG_SWEDISH} "Hydraulik"
LangString Pneumatic ${LANG_SWEDISH} "Pneumatik"
LangString Energy ${LANG_SWEDISH} "Energi"
LangString water ${LANG_SWEDISH} "Vatten"
LangString Refrigeration ${LANG_SWEDISH} "Kylning"
LangString Solar_thermal ${LANG_SWEDISH} "Solvarme"
LangString Lang ${LANG_SWEDISH} "Språk"
LangString Fonts ${LANG_SWEDISH} "Teckensnitt"
LangString Titleblocks ${LANG_SWEDISH} "Ritningshuvuden"
LangString Examples ${LANG_SWEDISH} "Exempel"
LangString Check ${LANG_SWEDISH} "Markera för att starta ${SOFT_NAME}"
LangString var1 ${LANG_SWEDISH} "Element från den officiella samlingen"
LangString var2 ${LANG_SWEDISH} "Språkfiler"
LangString var3 ${LANG_SWEDISH} "Exempel på ritningshuvuden"
LangString var4 ${LANG_SWEDISH} "Exempel på scheman"
LangString var5 ${LANG_SWEDISH} "Teckensnitt"
LangString uninstFailed ${LANG_SWEDISH} "Avinstallationen av den föregående versionen misslyckades.$\nAvinstallera ${SOFT_NAME} manuellt innan du fortsätter."
; ----------------------------------------------------------------
; Turkish (LANG_TURKISH)
; ----------------------------------------------------------------
LangString installed ${LANG_TURKISH} "${SOFT_NAME} zaten yüklü. $\n$\nÖnceki sürümü kaldırmak için `Tamam`'a, bu yükseltmeyi iptal etmek için `İptal`'e tıklayın."
LangString wrongArch ${LANG_TURKISH} "Bu dağıtım yalnızca 64 bit bilgisayarlar içindir."
LangString Elements ${LANG_TURKISH} "Elemanlar"
LangString Electric ${LANG_TURKISH} "Elektrik"
LangString Logic ${LANG_TURKISH} "Mantık"
LangString Hydraulic ${LANG_TURKISH} "Hidrolik"
LangString Pneumatic ${LANG_TURKISH} "Pnömatik"
LangString Energy ${LANG_TURKISH} "Enerji"
LangString water ${LANG_TURKISH} "Su"
LangString Refrigeration ${LANG_TURKISH} "Soğutma"
LangString Solar_thermal ${LANG_TURKISH} "Gunes_Is"
LangString Lang ${LANG_TURKISH} "Dil"
LangString Fonts ${LANG_TURKISH} "Yazı Tipleri"
LangString Titleblocks ${LANG_TURKISH} "Başlık Bloğu"
LangString Examples ${LANG_TURKISH} "Örnekler"
LangString Check ${LANG_TURKISH} "${SOFT_NAME}'i başlatmak için işaretleyin"
LangString var1 ${LANG_TURKISH} "Resmi koleksiyonun elemanları"
LangString var2 ${LANG_TURKISH} "Dil dosyaları"
LangString var3 ${LANG_TURKISH} "Başlık bloğu örnekleri"
LangString var4 ${LANG_TURKISH} "Şema örnekleri"
LangString var5 ${LANG_TURKISH} "Yazı Tipleri"
LangString uninstFailed ${LANG_TURKISH} "Önceki sürümün kaldırılması başarısız oldu.$\nDevam etmeden önce lütfen ${SOFT_NAME}'i manuel olarak kaldırın."
; ----------------------------------------------------------------
; Ukrainian (LANG_UKRAINIAN)
; ----------------------------------------------------------------
LangString installed ${LANG_UKRAINIAN} "${SOFT_NAME} вже встановлено. $\n$\nНатисніть `OK` для видалення попередньої версії або `Скасувати` для скасування оновлення."
LangString wrongArch ${LANG_UKRAINIAN} "Цей дистрибутив призначений лише для 64-розрядних комп'ютерів."
LangString Elements ${LANG_UKRAINIAN} "Елементи"
LangString Electric ${LANG_UKRAINIAN} "Електрика"
LangString Logic ${LANG_UKRAINIAN} "Логіка"
LangString Hydraulic ${LANG_UKRAINIAN} "Гідравліка"
LangString Pneumatic ${LANG_UKRAINIAN} "Пневматика"
LangString Energy ${LANG_UKRAINIAN} "Енергетика"
LangString water ${LANG_UKRAINIAN} "Водопостачання"
LangString Refrigeration ${LANG_UKRAINIAN} "Холодильна техніка"
LangString Solar_thermal ${LANG_UKRAINIAN} "Сонячно-теплова"
LangString Lang ${LANG_UKRAINIAN} "Мова"
LangString Fonts ${LANG_UKRAINIAN} "Шрифти"
LangString Titleblocks ${LANG_UKRAINIAN} "Штампи"
LangString Examples ${LANG_UKRAINIAN} "Приклади"
LangString Check ${LANG_UKRAINIAN} "Позначте для запуску ${SOFT_NAME}"
LangString var1 ${LANG_UKRAINIAN} "Елементи офіційної колекції"
LangString var2 ${LANG_UKRAINIAN} "Мовні файли"
LangString var3 ${LANG_UKRAINIAN} "Приклади штампів"
LangString var4 ${LANG_UKRAINIAN} "Приклади схем"
LangString var5 ${LANG_UKRAINIAN} "Шрифти"
LangString uninstFailed ${LANG_UKRAINIAN} "Видалення попередньої версії завершилося помилкою.$\nБудь ласка, видаліть ${SOFT_NAME} вручну перед продовженням."
; ----------------------------------------------------------------
; Chinese Simplified (LANG_SIMPCHINESE)
; ----------------------------------------------------------------
LangString installed ${LANG_SIMPCHINESE} "${SOFT_NAME} 已经安装。$\n$\n单击 $\"确定$\" 删除旧版本,或单击 $\"取消$\" 取消本次升级。"
LangString wrongArch ${LANG_SIMPCHINESE} "本安装包仅适用于 64 位计算机。"
LangString Elements ${LANG_SIMPCHINESE} "元件"
LangString Electric ${LANG_SIMPCHINESE} "电气"
LangString Logic ${LANG_SIMPCHINESE} "逻辑"
LangString Hydraulic ${LANG_SIMPCHINESE} "液压"
LangString Pneumatic ${LANG_SIMPCHINESE} "气动"
LangString Energy ${LANG_SIMPCHINESE} "能源"
LangString water ${LANG_SIMPCHINESE} ""
LangString Refrigeration ${LANG_SIMPCHINESE} "制冷"
LangString Solar_thermal ${LANG_SIMPCHINESE} "太阳能热"
LangString Lang ${LANG_SIMPCHINESE} "语言"
LangString Fonts ${LANG_SIMPCHINESE} "字体"
LangString Titleblocks ${LANG_SIMPCHINESE} "标题栏"
LangString Examples ${LANG_SIMPCHINESE} "示例"
LangString Check ${LANG_SIMPCHINESE} "勾选以启动 ${SOFT_NAME}"
LangString var1 ${LANG_SIMPCHINESE} "官方库元件"
LangString var2 ${LANG_SIMPCHINESE} "语言文件"
LangString var3 ${LANG_SIMPCHINESE} "标题栏示例"
LangString var4 ${LANG_SIMPCHINESE} "图纸示例"
LangString var5 ${LANG_SIMPCHINESE} "字体"
LangString uninstFailed ${LANG_SIMPCHINESE} "卸载旧版本失败。$\n请在继续之前手动卸载 ${SOFT_NAME}。"
+7
View File
@@ -88,6 +88,7 @@ set(QET_RES_FILES
${QET_DIR}/sources/ui/dynamicelementtextitemeditor.ui
${QET_DIR}/sources/ui/elementinfopartwidget.ui
${QET_DIR}/sources/ui/elementinfowidget.ui
${QET_DIR}/sources/ui/terminalnumberingdialog.ui
${QET_DIR}/sources/ui/formulaassistantdialog.ui
${QET_DIR}/sources/ui/imagepropertieswidget.ui
${QET_DIR}/sources/ui/importelementdialog.ui
@@ -112,6 +113,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/conductorautonumerotation.cpp
${QET_DIR}/sources/conductorautonumerotation.h
${QET_DIR}/sources/conductornumexport.cpp
${QET_DIR}/sources/wiringlistexport.h
${QET_DIR}/sources/wiringlistexport.cpp
${QET_DIR}/sources/conductornumexport.h
${QET_DIR}/sources/conductorprofile.cpp
${QET_DIR}/sources/conductorprofile.h
@@ -251,6 +254,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/diagramevent/diagrameventaddtext.h
${QET_DIR}/sources/diagramevent/diagrameventinterface.cpp
${QET_DIR}/sources/diagramevent/diagrameventinterface.h
${QET_DIR}/sources/diagramevent/diagrameventaddmacro.cpp
${QET_DIR}/sources/diagramevent/diagrameventaddmacro.h
${QET_DIR}/sources/dvevent/dveventinterface.cpp
${QET_DIR}/sources/dvevent/dveventinterface.h
@@ -630,6 +635,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/ui/elementinfopartwidget.h
${QET_DIR}/sources/ui/elementinfowidget.cpp
${QET_DIR}/sources/ui/elementinfowidget.h
${QET_DIR}/sources/ui/terminalnumberingdialog.cpp
${QET_DIR}/sources/ui/terminalnumberingdialog.h
${QET_DIR}/sources/ui/elementpropertieswidget.cpp
${QET_DIR}/sources/ui/elementpropertieswidget.h
${QET_DIR}/sources/ui/formulaassistantdialog.cpp
+777 -533
View File
File diff suppressed because it is too large Load Diff
+948 -665
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+5568 -620
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+785 -533
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+781 -536
View File
File diff suppressed because it is too large Load Diff
+779 -535
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+776 -532
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+1063 -905
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+14539
View File
File diff suppressed because it is too large Load Diff
+777 -534
View File
File diff suppressed because it is too large Load Diff
+779 -535
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+779 -535
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+779 -535
View File
File diff suppressed because it is too large Load Diff
+779 -535
View File
File diff suppressed because it is too large Load Diff
+779 -535
View File
File diff suppressed because it is too large Load Diff
+942 -664
View File
File diff suppressed because it is too large Load Diff
+777 -534
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+777 -533
View File
File diff suppressed because it is too large Load Diff
+23 -1
View File
@@ -7,7 +7,7 @@ Icon=qelectrotech
Terminal=false
Type=Application
MimeType=application/x-qet-project;application/x-qet-element;application/x-qet-titleblock;
Categories=Graphics;Qt;VectorGraphics;Science;Electricity;Engineering;
Categories=Graphics;
Keywords=Graphics;Science;Electricity;Engineering;
Comment=Edit electrical diagrams.
Comment[ar]=تحرير مخططات كهربائية
@@ -28,6 +28,17 @@ Comment[pl]=Edycja schematów elektrycznych
Comment[pt]=Criar esquemas eléctricos.
Comment[ru]=Создание и редактирование электрических схем.
Comment[sk]=Úprava elektrických schém.
Comment[hu]=Elektromos kapcsolási rajzok szerkesztése.
Comment[mn]=Цахилгааны схем засварлах.
Comment[nb]=Rediger elektriske diagrammer.
Comment[pt_BR]=Editar diagramas elétricos.
Comment[ro]=Editați diagrame electrice.
Comment[sl]=Uredite električne sheme.
Comment[sr]=Уређивање електричних дијаграма.
Comment[sv]=Redigera elektriska diagram.
Comment[tr]=Elektrik şemalarını düzenleyin.
Comment[uk]=Редагування електричних схем.
Comment[zh]=编辑电气图。
GenericName=Electrical diagram editor
GenericName[ar]=مُحرّر مخططات كهربائية
GenericName[be]=Elektrische schema editor
@@ -47,3 +58,14 @@ GenericName[pl]=Edytor schematów elektrycznych
GenericName[pt]=Editor de esquemas eléctricos.
GenericName[ru]=Редактор электрических схем
GenericName[sk]=Editor elektrických schém
GenericName[hu]=Elektromos kapcsolási rajz szerkesztő
GenericName[mn]=Цахилгааны схемийн засварлагч
GenericName[nb]=Elektrisk diagram editor
GenericName[pt_BR]=Editor de diagramas elétricos
GenericName[ro]=Editor de diagrame electrice
GenericName[sl]=Urejevalnik električnih shem
GenericName[sr]=Уређивач електричних дијаграма
GenericName[sv]=Elektriskt diagramredigerare
GenericName[tr]=Elektrik şeması düzenleyici
GenericName[uk]=Редактор електричних схем
GenericName[zh]=电气图编辑器
+86 -9
View File
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2006-2026 The QElectroTech Team -->
<application>
<id type="desktop">qelectrotech.desktop</id>
<component type="desktop-application">
<id>org.qelectrotech.QElectroTech</id>
<launchable type="desktop-id">org.qelectrotech.QElectroTech.desktop</launchable>
<metadata_license>MIT</metadata_license>
<project_license>GPL-2.0-or-later</project_license>
<name>QElectroTech</name>
@@ -23,9 +24,22 @@
<summary xml:lang="pl">Edytor schematów elektrycznych</summary>
<summary xml:lang="pt">Editor de esquemas eléctricos</summary>
<summary xml:lang="ru">Редактор электрических схем</summary>
<summary xml:lang="en">Electrical diagram editor</summary>
<summary xml:lang="hu">Elektromos kapcsolási rajz szerkesztő</summary>
<summary xml:lang="mn">Цахилгааны схемийн засварлагч</summary>
<summary xml:lang="nb">Elektrisk diagram editor</summary>
<summary xml:lang="pt_BR">Editor de diagramas elétricos</summary>
<summary xml:lang="ro">Editor de diagrame electrice</summary>
<summary xml:lang="sk">Editor elektrických schém</summary>
<summary xml:lang="sl">Urejevalnik električnih shem</summary>
<summary xml:lang="sr">Уређивач електричних дијаграма</summary>
<summary xml:lang="sv">Elektriskt diagramredigerare</summary>
<summary xml:lang="tr">Elektrik şeması düzenleyici</summary>
<summary xml:lang="uk">Редактор електричних схем</summary>
<summary xml:lang="zh">电气图编辑器</summary>
<content_rating type="oars-1.1"/>
<releases>
<release version="0.9-dev" date="2021-02-21"/>
<release version="0.100.1-dev" date="2026"/>
</releases>
<description>
<p>
@@ -92,10 +106,73 @@
QElectroTech - приложение написанное на Qt5 и предназначено для разработки электрических схем.
Приложение использует для хранения проектов и библиотек элементов файлы в XML формате. Приложение помимо редактора электричесих схем, содержит также редакторы элементов и редактор шаблонов листов.
</p>
<p xml:lang="hr">
QElectroTech je Qt5 aplikacija za projektiranje elektro shema.
Koristi XML datoteke za elemente i sheme, te uključuje uređivač shema, uređivač elemenata i uređivač zaglavlja.
</p>
<p xml:lang="hu">
A QElectroTech egy Qt5 alapú alkalmazás elektromos kapcsolási rajzok tervezéséhez.
XML fájlokat használ az elemekhez és rajzokhoz, és tartalmaz egy rajzszerkesztőt, egy elemszerkesztőt és egy fejlécszerkesztőt.
</p>
<p xml:lang="mn">
QElectroTech нь Qt5 дээр суурилсан цахилгааны схем зохиох програм юм.
Элемент болон схемүүдэд XML файл ашигладаг бөгөөд схем засварлагч, элемент засварлагч, гарчгийн блок засварлагчийг агуулдаг.
</p>
<p xml:lang="nb">
QElectroTech er et Qt5-program for å lage elektriske skjemaer.
Det bruker XML-filer for elementer og skjemaer, og inkluderer en skjemaeditor, en elementeditor og en tittelblokkreditor.
</p>
<p xml:lang="pt_BR">
QElectroTech é uma aplicação Qt5 para desenhar diagramas elétricos.
Utiliza arquivos XML para os elementos e diagramas, e inclui um editor de diagramas, um editor de elementos e um editor de cartuchos.
</p>
<p xml:lang="ro">
QElectroTech este o aplicație Qt5 pentru proiectarea schemelor electrice.
Utilizează fișiere XML pentru elemente și scheme, și include un editor de scheme, un editor de elemente și un editor de cartușe.
</p>
<p xml:lang="sk">
QElectroTech je Qt5 aplikácia na navrhovanie elektrických schém.
Pre prvky a schémy používa súbory XML a zahŕňa editor schém, editor prvkov a editor titulkových blokov.
</p>
<p xml:lang="sl">
QElectroTech je aplikacija Qt5 za načrtovanje električnih shem.
Za elemente in sheme uporablja datoteke XML ter vključuje urejevalnik shem, urejevalnik elementov in urejevalnik naslovnih blokov.
</p>
<p xml:lang="sr">
QElectroTech је Qt5 апликација за пројектовање електричних шема.
Користи XML датотеке за елементе и шеме, и укључује уређивач шема, уређивач елемената и уређивач заглавља.
</p>
<p xml:lang="sv">
QElectroTech är ett Qt5-program för att rita elektriska schema.
Det använder XML-filer för element och schema, och inkluderar en schemaredigerare, en elementredigerare och en titelblocksredigerare.
</p>
<p xml:lang="tr">
QElectroTech, elektrik şemaları tasarlamak için bir Qt5 uygulamasıdır.
Elemanlar ve şemalar için XML dosyaları kullanır; şema düzenleyicisi, eleman düzenleyicisi ve başlık bloğu düzenleyicisini içerir.
</p>
<p xml:lang="uk">
QElectroTech — це Qt5 застосунок для проектування електричних схем.
Використовує XML-файли для елементів і схем, і включає редактор схем, редактор елементів та редактор основних написів.
</p>
<p xml:lang="zh">
QElectroTech 是一款基于 Qt5 的电气图设计应用程序。
它使用 XML 文件存储元件和图纸,包含图纸编辑器、元件编辑器和标题栏编辑器。
</p>
</description>
<url type="homepage">http://qelectrotech.org</url>
<screenshots>
<screenshot type="default">http://download.tuxfamily.org/qet/screens/qelectrotech5.png</screenshot>
</screenshots>
<updatecontact>qet@lists.tuxfamily.org</updatecontact>
</application>
<url type="homepage">https://qelectrotech.org</url>
<url type="bugtracker">https://qelectrotech.org/bugtracker</url>
<url type="vcs-browser">https://github.com/qelectrotech/qelectrotech-source-mirror</url>
<developer id="org.qelectrotech">
<name>QElectroTech</name>
</developer>
<screenshot type="default">
<image>https://qelectrotech.org/screenshots/qet_overview04.png</image>
</screenshot>
<screenshot>
<image>https://qelectrotech.org/screenshots/qet_overview06.png</image>
</screenshot>
<screenshot>
<image>https://qelectrotech.org/screenshots/qet_overview09.png</image>
</screenshot>
<update_contact>scorpio@qelectrotech.org</update_contact>
</component>
+39
View File
@@ -19,6 +19,19 @@
<comment xml:lang="pl">Plik projektu QElectrotech</comment>
<comment xml:lang="pt">Ficheiro de projecto QElectroTech</comment>
<comment xml:lang="ru">Файл проекта QElectroTech</comment>
<comment xml:lang="hr">QElectroTech datoteka projekta</comment>
<comment xml:lang="hu">QElectroTech projektfájl</comment>
<comment xml:lang="mn">QElectroTech төслийн файл</comment>
<comment xml:lang="nb">QElectroTech prosjektfil</comment>
<comment xml:lang="pt_BR">Arquivo de projeto QElectroTech</comment>
<comment xml:lang="ro">Fișier proiect QElectroTech</comment>
<comment xml:lang="sk">Súbor projektu QElectroTech</comment>
<comment xml:lang="sl">Datoteka projekta QElectroTech</comment>
<comment xml:lang="sr">QElectroTech датотека пројекта</comment>
<comment xml:lang="sv">QElectroTech projektfil</comment>
<comment xml:lang="tr">QElectroTech proje dosyası</comment>
<comment xml:lang="uk">Файл проєкту QElectroTech</comment>
<comment xml:lang="zh">QElectroTech 项目文件</comment>
<glob pattern="*.qet" />
</mime-type>
<mime-type type="application/x-qet-element">
@@ -40,6 +53,19 @@
<comment xml:lang="pl">Plik elementu QElectroTech</comment>
<comment xml:lang="pt">Ficheiro de projecto QElectroTech</comment>
<comment xml:lang="ru">Файл элемента QElectroTech</comment>
<comment xml:lang="hr">QElectroTech datoteka elementa</comment>
<comment xml:lang="hu">QElectroTech elemfájl</comment>
<comment xml:lang="mn">QElectroTech элементийн файл</comment>
<comment xml:lang="nb">QElectroTech elementfil</comment>
<comment xml:lang="pt_BR">Arquivo de elemento QElectroTech</comment>
<comment xml:lang="ro">Fișier element QElectroTech</comment>
<comment xml:lang="sk">Súbor prvku QElectroTech</comment>
<comment xml:lang="sl">Datoteka elementa QElectroTech</comment>
<comment xml:lang="sr">QElectroTech датотека елемента</comment>
<comment xml:lang="sv">QElectroTech elementfil</comment>
<comment xml:lang="tr">QElectroTech eleman dosyası</comment>
<comment xml:lang="uk">Файл елемента QElectroTech</comment>
<comment xml:lang="zh">QElectroTech 元件文件</comment>
<glob pattern="*.elmt" />
</mime-type>
<mime-type type="application/x-qet-titleblock">
@@ -61,6 +87,19 @@
<comment xml:lang="pl">Szablon tabliczki rysunkowej QElectroTech</comment>
<comment xml:lang="pt">Modelo de moldura QElectroTech</comment>
<comment xml:lang="ru">Файл шаблона основной надписи листа QElectroTech</comment>
<comment xml:lang="hr">QElectroTech predložak zaglavlja datoteke</comment>
<comment xml:lang="hu">QElectroTech fejlécsablon fájl</comment>
<comment xml:lang="mn">QElectroTech гарчгийн блокын загварын файл</comment>
<comment xml:lang="nb">QElectroTech tittelblokk malfil</comment>
<comment xml:lang="pt_BR">Arquivo de modelo de cartuco QElectroTech</comment>
<comment xml:lang="ro">Fișier șablon cartus QElectroTech</comment>
<comment xml:lang="sk">Súbor šablóny titulkového bloku QElectroTech</comment>
<comment xml:lang="sl">Datoteka predloge naslovnega bloka QElectroTech</comment>
<comment xml:lang="sr">QElectroTech датотека шаблона заглавља</comment>
<comment xml:lang="sv">QElectroTech titelblocksmall-fil</comment>
<comment xml:lang="tr">QElectroTech başlık bloğu şablon dosyası</comment>
<comment xml:lang="uk">Файл шаблону основного напису QElectroTech</comment>
<comment xml:lang="zh">QElectroTech 标题栏模板文件</comment>
<glob pattern="*.titleblock" />
</mime-type>
</mime-info>
+3 -3
View File
@@ -243,18 +243,18 @@ if [[ $a == "Y" || $a == "y" ]]; then
cd $DEFAULT_DIR
cp -r nsis_base nsis_base64$HEAD
cd qelectrotech-$VERSION.r$HEAD/
cp -r {elements,examples,titleblocks} /$DEFAULT_DIR/nsis_base64$HEAD/files
cp -r {elements,examples,titleblocks,fonts} /$DEFAULT_DIR/nsis_base64$HEAD/files
cp -r lang/*.qm /$DEFAULT_DIR/nsis_base64$HEAD/files/lang
cd $DEFAULT_DIR
cd qelectrotech-$VERSION.r$HEAD/build-aux/windows/
cp {lang_extra.nsh,QET64.nsi,lang_extra_fr.nsh} /$DEFAULT_DIR/nsis_base64$HEAD/
cp {lang_extra.nsh,QET64.nsi,lang_extra_fr.nsh,lang_extra_missing.nsh} /$DEFAULT_DIR/nsis_base64$HEAD/
#copy and update folders of readytouse_base skeleton
cd $DEFAULT_DIR
cp -r readytouse_base qelectrotech-$VERSION+git$HEAD-x86-win64-readytouse
cd qelectrotech-$VERSION.r$HEAD/
cp -r {elements,examples,titleblocks} /$DEFAULT_DIR/qelectrotech-$VERSION+git$HEAD-x86-win64-readytouse
cp -r {elements,examples,titleblocks,fonts} /$DEFAULT_DIR/qelectrotech-$VERSION+git$HEAD-x86-win64-readytouse
cp -r lang/*.qm /$DEFAULT_DIR/qelectrotech-$VERSION+git$HEAD-x86-win64-readytouse/lang
export PATH=/home/laurent/digikam3333/project/bundles/mxe/build.win64/usr/bin:$PATH
@@ -119,8 +119,8 @@ int ElementCollectionItem::rowForInsertItem(const QString &name)
return -1;
QList <ElementCollectionItem *> child;
//The item to insert is an element we search from element child
if (name.endsWith(".elmt"))
//The item to insert is an element/template we search from element child
if (name.endsWith(".elmt") || name.endsWith(".qetmak"))
{
child = elementsDirectChild();
//There isn't element, we insert at last position
@@ -264,10 +264,12 @@ bool ElementsCollectionModel::dropMimeData(const QMimeData *data,
@param projects : list of projects to load
*/
void ElementsCollectionModel::loadCollections(bool common_collection,
bool company_collection,
bool custom_collection,
QList<QETProject *> projects)
bool company_collection,
bool custom_collection,
QList<QETProject *> projects)
{
clear();
m_items_list_to_setUp.clear();
if (common_collection)
@@ -280,36 +282,64 @@ void ElementsCollectionModel::loadCollections(bool common_collection,
if (common_collection || company_collection || custom_collection)
m_items_list_to_setUp.append(items());
for (QETProject *project : projects)
{
addProject(project, false);
m_items_list_to_setUp.append(projectItems(project));
}
auto *watcher = new QFutureWatcher<void>();
connect(watcher, &QFutureWatcher<void>::progressValueChanged,
this, &ElementsCollectionModel::loadingProgressValueChanged);
this, &ElementsCollectionModel::loadingProgressValueChanged);
connect(watcher, &QFutureWatcher<void>::progressRangeChanged,
this, &ElementsCollectionModel::loadingProgressRangeChanged);
this, &ElementsCollectionModel::loadingProgressRangeChanged);
connect(watcher, &QFutureWatcher<void>::finished,
this, &ElementsCollectionModel::loadingFinished);
connect(
watcher,
&QFutureWatcher<void>::finished,
watcher,
&QFutureWatcher<void>::deleteLater);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
this, &ElementsCollectionModel::loadingFinished);
connect(watcher, &QFutureWatcher<void>::finished, watcher, &QFutureWatcher<void>::deleteLater);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
m_future = QtConcurrent::map(m_items_list_to_setUp, setUpData);
#else
# if TODO_LIST
# pragma message("@TODO remove code for QT 6 or later")
# endif
qDebug() << "Help code for QT 6 or later"
<< "QtConcurrent::run its backwards now...function, object, args";
#endif
#else
qDebug() << "Help code for QT 6 or later";
#endif
watcher->setFuture(m_future);
}
/**
* @brief ElementsCollectionModel::loadMacrosCollection
* Load the macros collection synchronously to avoid thread-collisions.
*/
void ElementsCollectionModel::loadMacrosCollection()
{
m_items_list_to_setUp.clear();
addMacrosCollection(true);
}
/**
* @brief ElementsCollectionModel::addMacrosCollection
* Add the user macros collection to this model
* @param set_data
*/
void ElementsCollectionModel::addMacrosCollection(bool set_data)
{
QString macrosPath = QETApp::userMacrosDir();
qDebug() << "=== MAKRO PFAD CHECK ===" << macrosPath;
if (macrosPath.endsWith("/")) {
macrosPath.remove(macrosPath.length() - 1, 1);
}
FileElementCollectionItem *feci = new FileElementCollectionItem();
if (feci->setRootPath(macrosPath,
set_data,
m_hide_element)) {
invisibleRootItem()->appendRow(feci);
if (set_data)
feci->setUpData();
}
else
delete feci;
}
/**
@brief ElementsCollectionModel::addCommonCollection
Add the common elements collection to this model
@@ -368,11 +398,11 @@ void ElementsCollectionModel::addCustomCollection(bool set_data)
}
/**
@brief ElementsCollectionModel::addLocation
Add the element or directory to this model.
If the location is already managed by this model, do nothing.
@param location
*/
* @brief ElementsCollectionModel::addLocation
* Add the element or directory to this model.
* If the location is already managed by this model, do nothing.
* @param location
*/
void ElementsCollectionModel::addLocation(const ElementsLocation& location)
{
QModelIndex index = indexFromLocation(location);
@@ -387,14 +417,15 @@ void ElementsCollectionModel::addLocation(const ElementsLocation& location)
if (project) {
XmlProjectElementCollectionItem *xpeci =
m_project_hash.value(project);
m_project_hash.value(project);
last_item = xpeci->lastItemForPath(
location.collectionPath(false),
collection_name);
location.collectionPath(false),
collection_name);
}
}
else if (location.isCustomCollection()) {
// ANPASSUNG: Makros und Custom Collection werden hier behandelt!
else if (location.isCustomCollection() || location.isMacrosCollection()) {
QList <ElementCollectionItem *> child_list;
for (int i=0 ; i<rowCount() ; i++)
@@ -404,15 +435,18 @@ void ElementsCollectionModel::addLocation(const ElementsLocation& location)
if (eci->type() == FileElementCollectionItem::Type) {
FileElementCollectionItem *feci =
static_cast<FileElementCollectionItem *>(eci);
static_cast<FileElementCollectionItem *>(eci);
// Wir prüfen explizit, ob es Custom ODER Macros ist, und weisen es richtig zu.
if ((location.isCustomCollection() && feci->isCustomCollection()) ||
(location.isMacrosCollection() && feci->isMacrosCollection())) {
if (feci->isCustomCollection()) {
last_item = feci->lastItemForPath(
location.collectionPath(false),
collection_name);
location.collectionPath(false),
collection_name);
if(last_item)
break;
}
}
}
}
}
@@ -574,14 +608,14 @@ void ElementsCollectionModel::hideElement()
}
/**
@brief ElementsCollectionModel::indexFromLocation
Return the index who represent location.
Index can be non valid
@param location
@return
*/
* @brief ElementsCollectionModel::indexFromLocation
* Return the index who represent location.
* Index can be non valid
* @param location
* @return
*/
QModelIndex ElementsCollectionModel::indexFromLocation(
const ElementsLocation &location)
const ElementsLocation &location)
{
QList <ElementCollectionItem *> child_list;
@@ -589,30 +623,34 @@ QModelIndex ElementsCollectionModel::indexFromLocation(
child_list.append(static_cast<ElementCollectionItem *>(item(i)));
}
foreach(ElementCollectionItem *eci, child_list) {
foreach(ElementCollectionItem *eci, child_list) {
ElementCollectionItem *match_eci = nullptr;
ElementCollectionItem *match_eci = nullptr;
if (eci->type() == FileElementCollectionItem::Type) {
if (FileElementCollectionItem *feci = static_cast<FileElementCollectionItem *>(eci)) {
if ( (location.isCommonCollection() && feci->isCommonCollection()) ||
(location.isCompanyCollection() && feci->isCompanyCollection()) ||
(location.isCustomCollection() && !feci->isCommonCollection()) ) {
match_eci = feci->itemAtPath(location.collectionPath(false));
if (eci->type() == FileElementCollectionItem::Type) {
if (FileElementCollectionItem *feci = static_cast<FileElementCollectionItem *>(eci)) {
// ANPASSUNG: Makro-Prüfung hinzugefügt, damit das Modell den Pfad im Baum findet!
if ( (location.isCommonCollection() && feci->isCommonCollection()) ||
(location.isCompanyCollection() && feci->isCompanyCollection()) ||
(location.isMacrosCollection() && feci->isMacrosCollection()) ||
(location.isCustomCollection() && feci->isCustomCollection()) ) {
match_eci = feci->itemAtPath(location.collectionPath(false));
}
}
}
else if (eci->type() == XmlProjectElementCollectionItem::Type) {
if (XmlProjectElementCollectionItem *xpeci = static_cast<XmlProjectElementCollectionItem *>(eci)) {
match_eci = xpeci->itemAtPath(location.collectionPath(false));
}
}
else if (eci->type() == XmlProjectElementCollectionItem::Type) {
if (XmlProjectElementCollectionItem *xpeci = static_cast<XmlProjectElementCollectionItem *>(eci)) {
match_eci = xpeci->itemAtPath(location.collectionPath(false));
}
if (match_eci)
return indexFromItem(match_eci);
}
return QModelIndex();
if (match_eci)
return indexFromItem(match_eci);
}
return QModelIndex();
}
/**
@@ -47,6 +47,8 @@ class ElementsCollectionModel : public QStandardItemModel
void addCommonCollection(bool set_data = true);
void addCompanyCollection(bool set_data = true);
void addCustomCollection(bool set_data = true);
void addMacrosCollection(bool set_data = true);
void loadMacrosCollection();
void addLocation(const ElementsLocation& location);
void addProject(QETProject *project, bool set_data = true);
@@ -93,10 +93,7 @@ void ElementsCollectionWidget::addProject(QETProject *project)
{
if (m_model)
{
m_progress_bar->show();
m_tree_view->setDisabled(true);
QList <QETProject *> prj; prj.append(project);
m_model->loadCollections(false, false, false, prj);
m_model->addProject(project, true);
}
else {
m_waiting_project.append(project);
@@ -176,16 +173,14 @@ void ElementsCollectionWidget::setUpAction()
*/
void ElementsCollectionWidget::setUpWidget()
{
//Setup the main layout
m_main_vlayout = new QVBoxLayout(this);
this->setLayout(m_main_vlayout);
m_main_vlayout->setContentsMargins(0, 0, 0, 0);
m_main_vlayout->setSpacing(2);
m_search_field = new QLineEdit(this);
m_search_field->setPlaceholderText(tr("Rechercher"));
m_search_field->setPlaceholderText(tr("Rechercher..."));
m_search_field->setClearButtonEnabled(true);
m_main_vlayout->addWidget(m_search_field);
//Setup the tree view
m_tree_view = new ElementsTreeView(this);
m_tree_view->setHeaderHidden(true);
m_tree_view->setIconSize(QSize(50, 50));
@@ -195,12 +190,29 @@ void ElementsCollectionWidget::setUpWidget()
m_tree_view->setAnimated(true);
m_tree_view->setMouseTracking(true);
m_tree_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_main_vlayout->addWidget(m_tree_view);
//Setup the progress bar
//Setup the macros tree view
m_macros_tree_view = new ElementsTreeView(this);
m_macros_tree_view->setHeaderHidden(true);
m_macros_tree_view->setIconSize(QSize(50, 50));
m_macros_tree_view->setDragDropMode(QAbstractItemView::DragDrop);
m_macros_tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
m_macros_tree_view->setAutoExpandDelay(500);
m_macros_tree_view->setAnimated(true);
m_macros_tree_view->setMouseTracking(true);
m_macros_tree_view->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_tab_widget = new QTabWidget(this);
m_tab_widget->setDocumentMode(true);
m_tab_widget->setTabPosition(QTabWidget::North);
m_tab_widget->addTab(m_tree_view, tr("Collections"));
m_tab_widget->addTab(m_macros_tree_view, tr("Modèles"));
m_main_vlayout->addWidget(m_search_field);
m_main_vlayout->addWidget(m_tab_widget);
m_progress_bar = new QProgressBar(this);
m_progress_bar->setFormat(QObject::tr("chargement %p% (%v sur %m)"));
m_main_vlayout->addWidget(m_progress_bar);
m_progress_bar->hide();
@@ -243,11 +255,15 @@ void ElementsCollectionWidget::setUpConnection()
this, &ElementsCollectionWidget::dirProperties);
connect(m_tree_view, &QTreeView::doubleClicked,
[this](const QModelIndex &index)
{
this->m_index_at_context_menu = index ;
this->editElement();
});
[this](const QModelIndex &index)
{
this->m_index_at_context_menu = index ;
ElementCollectionItem *eci = elementCollectionItemForIndex(index);
if (eci && eci->collectionPath().endsWith(".qetmak")) {
return; // Do nothing on double click for macros
}
this->editElement();
});
connect(m_tree_view, &QTreeView::entered,
[this] (const QModelIndex &index) {
@@ -256,37 +272,64 @@ void ElementsCollectionWidget::setUpConnection()
if (qde && eci)
qde->statusBar()->showMessage(eci->localName());
});
connect(m_macros_tree_view, &QTreeView::customContextMenuRequested,
this, &ElementsCollectionWidget::customContextMenu);
connect(m_macros_tree_view, &QTreeView::doubleClicked,
[this](const QModelIndex &index)
{
this->m_index_at_context_menu = index ;
ElementCollectionItem *eci = elementCollectionItemForIndex(index);
if (eci && eci->collectionPath().endsWith(".qetmak")) {
return; // Do nothing on double click for macros
}
this->editElement();
});
connect(m_macros_tree_view, &QTreeView::entered,
[this] (const QModelIndex &index) {
QETDiagramEditor *qde = QETApp::diagramEditorAncestorOf(this);
ElementCollectionItem *eci = elementCollectionItemForIndex(index);
if (qde && eci)
qde->statusBar()->showMessage(eci->localName());
});
}
/**
@brief ElementsCollectionWidget::customContextMenu
Display the context menu of this widget at point
@param point
*/
* @brief ElementsCollectionWidget::customContextMenu
* Display the context menu of this widget at point
* @param point
*/
void ElementsCollectionWidget::customContextMenu(const QPoint &point)
{
m_index_at_context_menu = m_tree_view->indexAt(point);
QTreeView *clicked_tree = qobject_cast<QTreeView *>(sender());
if (!clicked_tree) clicked_tree = m_tree_view; // Fallback
m_index_at_context_menu = clicked_tree->indexAt(point);
if (!m_index_at_context_menu.isValid()) return;
m_context_menu->clear();
ElementCollectionItem *eci = elementCollectionItemForIndex(
m_index_at_context_menu);
m_index_at_context_menu);
bool add_open_dir = false;
if (eci->isElement())
if (eci->isElement() && !eci->collectionPath().endsWith(".qetmak"))
m_context_menu->addAction(m_edit_element);
if (eci->type() == FileElementCollectionItem::Type)
{
add_open_dir = true;
FileElementCollectionItem *feci =
static_cast<FileElementCollectionItem*>(eci);
static_cast<FileElementCollectionItem*>(eci);
if (!feci->isCommonCollection())
{
if (feci->isDir())
{
m_context_menu->addAction(m_new_element);
if (!feci->isMacrosCollection()) {
m_context_menu->addAction(m_new_element);
}
m_context_menu->addAction(m_new_directory);
if (!feci->isCollectionRoot())
{
@@ -301,7 +344,7 @@ void ElementsCollectionWidget::customContextMenu(const QPoint &point)
if (eci->type() == XmlProjectElementCollectionItem::Type)
{
XmlProjectElementCollectionItem *xpeci =
static_cast<XmlProjectElementCollectionItem *>(eci);
static_cast<XmlProjectElementCollectionItem *>(eci);
if (xpeci->isCollectionRoot())
add_open_dir = true;
}
@@ -320,7 +363,7 @@ void ElementsCollectionWidget::customContextMenu(const QPoint &point)
m_context_menu->addAction(m_open_dir);
m_context_menu->addAction(m_reload);
m_context_menu->popup(mapToGlobal(m_tree_view->mapToParent(point)));
m_context_menu->popup(mapToGlobal(clicked_tree->mapToParent(point)));
}
/**
@@ -360,6 +403,9 @@ void ElementsCollectionWidget::editElement()
if ( !(eci && eci->isElement()) ) return;
// Prevent the element editor from opening for macros
if (eci->collectionPath().endsWith(".qetmak")) return;
ElementsLocation location(eci->collectionPath());
QETApp *app = QETApp::instance();
@@ -384,11 +430,15 @@ void ElementsCollectionWidget::deleteElement()
if (!eci) return;
ElementsLocation loc(eci->collectionPath());
if (! (loc.isElement()
&& loc.exist()
&& loc.isFileSystem()
&& (loc.collectionPath().startsWith("company://")
|| loc.collectionPath().startsWith("custom://"))) ) return;
bool isDeletableFile = loc.isElement() || eci->collectionPath().endsWith(".qetmak");
if (! (isDeletableFile
&& loc.exist()
&& loc.isFileSystem()
&& (loc.collectionPath().startsWith("company://")
|| loc.collectionPath().startsWith("custom://")
|| loc.collectionPath().startsWith("macros://"))) ) return;
if (QET::QetMessageBox::question(
this,
@@ -400,9 +450,10 @@ void ElementsCollectionWidget::deleteElement()
QFile file(loc.fileSystemPath());
if (file.remove())
{
m_model->removeRows(m_index_at_context_menu.row(),
1,
m_index_at_context_menu.parent());
QAbstractItemModel *clicked_model = const_cast<QAbstractItemModel*>(m_index_at_context_menu.model());
if (clicked_model) {
clicked_model->removeRows(m_index_at_context_menu.row(), 1, m_index_at_context_menu.parent());
}
}
else
{
@@ -429,10 +480,11 @@ void ElementsCollectionWidget::deleteDirectory()
ElementsLocation loc (eci->collectionPath());
if (! (loc.isDirectory()
&& loc.exist()
&& loc.isFileSystem()
&& (loc.collectionPath().startsWith("company://")
|| loc.collectionPath().startsWith("custom://"))) ) return;
&& loc.exist()
&& loc.isFileSystem()
&& (loc.collectionPath().startsWith("company://")
|| loc.collectionPath().startsWith("custom://")
|| loc.collectionPath().startsWith("macros://"))) ) return;
if (QET::QetMessageBox::question(
this,
@@ -445,9 +497,10 @@ void ElementsCollectionWidget::deleteDirectory()
QDir dir (loc.fileSystemPath());
if (dir.removeRecursively())
{
m_model->removeRows(m_index_at_context_menu.row(),
1,
m_index_at_context_menu.parent());
QAbstractItemModel *clicked_model = const_cast<QAbstractItemModel*>(m_index_at_context_menu.model());
if (clicked_model) {
clicked_model->removeRows(m_index_at_context_menu.row(), 1, m_index_at_context_menu.parent());
}
}
else
{
@@ -489,19 +542,29 @@ void ElementsCollectionWidget::editDirectory()
*/
void ElementsCollectionWidget::newDirectory()
{
ElementCollectionItem *eci = elementCollectionItemForIndex(
m_index_at_context_menu);
ElementCollectionItem *eci = elementCollectionItemForIndex(m_index_at_context_menu);
if (eci->type() != FileElementCollectionItem::Type) return;
if (!eci || eci->type() != FileElementCollectionItem::Type) return;
FileElementCollectionItem *feci =
static_cast<FileElementCollectionItem*>(eci);
FileElementCollectionItem *feci = static_cast<FileElementCollectionItem*>(eci);
if(feci->isCommonCollection()) return;
ElementsLocation location(feci->collectionPath());
ElementsCategoryEditor new_dir_editor(location, false, this);
if (new_dir_editor.exec() == QDialog::Accepted)
m_model->addLocation(new_dir_editor.createdLocation());
if (new_dir_editor.exec() == QDialog::Accepted) {
ElementsLocation new_loc = new_dir_editor.createdLocation();
if (new_loc.isMacrosCollection()) {
if (m_macros_model) {
m_macros_model->addLocation(new_loc);
}
} else {
if (m_model) {
m_model->addLocation(new_loc);
}
}
}
}
/**
@@ -662,12 +725,19 @@ void ElementsCollectionWidget::reload()
&ElementsCollectionWidget::loadingFinished);
m_new_model->loadCollections(true, true, true, project_list);
if (m_macros_model) {
m_macros_model->deleteLater();
}
m_macros_model = new ElementsCollectionModel(m_macros_tree_view);
m_macros_tree_view->setModel(m_macros_model);
m_macros_model->loadMacrosCollection();
}
/**
@brief ElementsCollectionWidget::loadingFinished
Process when collection finished to be loaded
*/
* @brief ElementsCollectionWidget::loadingFinished
* Process when collection finished to be loaded
*/
void ElementsCollectionWidget::loadingFinished()
{
if (m_new_model)
@@ -842,15 +912,21 @@ void ElementsCollectionWidget::showAndExpandItem(const QModelIndex &index,
}
/**
@brief ElementsCollectionWidget::elementCollectionItemForIndex
@param index
@return The internal pointer of index casted to ElementCollectionItem;
*/
ElementCollectionItem *ElementsCollectionWidget::elementCollectionItemForIndex(
const QModelIndex &index) {
if (!index.isValid())
return nullptr;
* @brief ElementsCollectionWidget::elementCollectionItemForIndex
* @param index
* @return The internal pointer of index casted to ElementCollectionItem;
*/
ElementCollectionItem *ElementsCollectionWidget::elementCollectionItemForIndex(const QModelIndex &index)
{
if (!index.isValid()) return nullptr;
return static_cast<ElementCollectionItem*>(
m_model->itemFromIndex(index));
if (m_macros_model && index.model() == m_macros_model) {
return static_cast<ElementCollectionItem *>(m_macros_model->itemFromIndex(index));
}
if (m_model && index.model() == m_model) {
return static_cast<ElementCollectionItem *>(m_model->itemFromIndex(index));
}
return nullptr;
}
@@ -25,6 +25,8 @@
#include <QTimer>
#include <QElapsedTimer>
#include <QScopedPointer>
#include <QTabWidget>
#include <QTreeView>
class ElementsCollectionModel;
class QVBoxLayout;
@@ -90,9 +92,12 @@ class ElementsCollectionWidget : public QWidget
private:
ElementsCollectionModel *m_model = nullptr;
ElementsCollectionModel *m_new_model = nullptr;
ElementsCollectionModel *m_macros_model = nullptr;
QLineEdit *m_search_field;
QTimer m_search_timer;
ElementsTreeView *m_tree_view;
ElementsTreeView *m_macros_tree_view = nullptr;
QTabWidget *m_tab_widget = nullptr;
QVBoxLayout *m_main_vlayout;
QMenu *m_context_menu;
QModelIndex m_index_at_context_menu;
+48 -41
View File
@@ -181,7 +181,7 @@ QString ElementsLocation::collectionPath(bool protocol) const
else
{
QString path = m_collection_path;
return path.remove(QRegularExpression("common://|company://|custom://|embed://"));
return path.remove(QRegularExpression("common://|company://|custom://|macros://|embed://"));
}
}
@@ -232,54 +232,34 @@ QString ElementsLocation::path() const
(start by common://, company://, custom:// or embed://) or not.
@param path
*/
void ElementsLocation::setPath(const QString &path)
{
QString tmp_path = path;
#ifdef Q_OS_WIN32
//On windows, we convert backslash to slash
#ifdef Q_OS_WIN32
tmp_path = QDir::fromNativeSeparators(path);
#endif
#endif
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
//There is a project, the path is for an embedded coolection.
if (m_project)
{
m_collection_path = path;
//Add the protocol to the collection path
if (!path.startsWith("embed://"))
m_collection_path.prepend("embed://");
}
//The path start with project, we get the project and the path from the string
else if (tmp_path.startsWith("project"))
{
QRegularExpression re
("^project(?<project_id>[0-9])\\+(?<collection_path>embed://*.*)$");
if (!re.isValid())
{
qWarning() <<QObject::tr("this is an error in the code")
<< re.errorString()
<< re.patternErrorOffset();
return;
}
QRegularExpression re ("^project(?<project_id>[0-9])\\+(?<collection_path>embed://*.*)$");
if (!re.isValid()) return;
QRegularExpressionMatch match = re.match(tmp_path);
if (!match.hasMatch())
{
qDebug()<<"no Match => return"
<<tmp_path;
return;
}
if (!match.hasMatch()) return;
bool conv_ok;
uint project_id = match.captured("project_id").toUInt(&conv_ok);
if (!conv_ok)
{
qWarning()<<"toUint failed"
<<match.captured("project_id")
<<re
<<tmp_path;
return;
}
if (!conv_ok) return;
QETProject *project = QETApp::project(project_id);
if (project)
{
@@ -287,10 +267,7 @@ void ElementsLocation::setPath(const QString &path)
m_project = project;
}
}
// The path is in file system,
// the given path is relative to common or custom collection
else if (path.startsWith("common://") || path.startsWith("company://") || path.startsWith("custom://"))
else if (path.startsWith("common://") || path.startsWith("company://") || path.startsWith("custom://") || path.startsWith("macros://"))
{
QString p;
if (path.startsWith("common://"))
@@ -303,6 +280,11 @@ void ElementsLocation::setPath(const QString &path)
tmp_path.remove("company://");
p = QETApp::companyElementsDirN() % "/" % tmp_path;
}
else if (path.startsWith("macros://"))
{
tmp_path.remove("macros://");
p = macrosPath % "/" % tmp_path;
}
else
{
tmp_path.remove("custom://");
@@ -312,11 +294,10 @@ void ElementsLocation::setPath(const QString &path)
m_file_system_path = p;
m_collection_path = path;
}
//In this case, the path is supposed to be relative to the file system.
else
{
QString path_ = path;
if(path_.endsWith(".elmt"))
if(path_.endsWith(".elmt") || path_.endsWith(".qetmak"))
{
m_file_system_path = path_;
if (path_.startsWith(QETApp::commonElementsDirN()))
@@ -331,6 +312,13 @@ void ElementsLocation::setPath(const QString &path)
path_.prepend("company://");
m_collection_path = path_;
}
else if (path_.startsWith(macrosPath))
{
QString matchPath = macrosPath + "/";
path_.remove(matchPath);
path_.prepend("macros://");
m_collection_path = path_;
}
else if (path_.startsWith(QETApp::customElementsDirN()))
{
path_.remove(QETApp::customElementsDirN()+="/");
@@ -353,6 +341,13 @@ void ElementsLocation::setPath(const QString &path)
path_.prepend("company://");
m_collection_path = path_;
}
else if (path_.startsWith(macrosPath))
{
QString matchPath = macrosPath + "/";
path_.remove(matchPath);
path_.prepend("macros://");
m_collection_path = path_;
}
else if (path_.startsWith(QETApp::customElementsDirN()))
{
path_.remove(QETApp::customElementsDirN()+="/");
@@ -371,10 +366,11 @@ void ElementsLocation::setPath(const QString &path)
*/
bool ElementsLocation::addToPath(const QString &string)
{
if (m_collection_path.endsWith(".elmt", Qt::CaseInsensitive))
if (m_collection_path.endsWith(".elmt", Qt::CaseInsensitive) ||
m_collection_path.endsWith(".qetmak", Qt::CaseInsensitive))
{
qDebug() << "ElementsLocation::addToPath :"
" Can't add string to the path of an element";
" Can't add string to the path of an element or template";
return(false);
}
@@ -477,7 +473,7 @@ QString ElementsLocation::toString() const
*/
bool ElementsLocation::isElement() const
{
return m_collection_path.endsWith(".elmt");
return m_collection_path.endsWith(".elmt") || m_collection_path.endsWith(".qetmak");
}
/**
@@ -942,3 +938,14 @@ QDebug operator<< (QDebug debug, const ElementsLocation &location)
return debug;
}
/**
* @brief ElementsLocation::isMacrosCollection
* @return True if this location represent an item from the macros collection
*/
bool ElementsLocation::isMacrosCollection() const
{
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
return fileSystemPath().startsWith(macrosPath);
}
@@ -78,6 +78,7 @@ class ElementsLocation
bool isCommonCollection() const;
bool isCompanyCollection() const;
bool isCustomCollection() const;
bool isMacrosCollection() const;
bool isProject() const;
bool exist() const;
bool isWritable() const;
+105 -2
View File
@@ -22,7 +22,12 @@
#include "../qeticons.h"
#include "elementcollectionitem.h"
#include "elementslocation.h"
#include "../qetproject.h"
#include "../diagram.h"
#include "xmlelementcollection.h"
#include "../NameList/nameslist.h"
#include <QPainter>
#include <QScopedPointer>
#include <QDrag>
#include <QStandardItemModel>
@@ -95,9 +100,107 @@ void ElementsTreeView::startElementDrag(const ElementsLocation &location)
if (location.isDirectory())
{
mime_data->setData("application/x-qet-category-uri",
location_str.toLatin1());
location_str.toLatin1());
drag->setPixmap(QET::Icons::Folder.pixmap(22, 22));
}
else if (location.fileName().endsWith(".qetmak"))
{
mime_data->setData("application/x-qet-element-uri", location_str.toLatin1());
QPixmap macro_pixmap;
// --- MINI-RENDERER FÜR DAS MAKRO-VORSCHAUBILD ---
QFile file(location.fileSystemPath());
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QDomDocument macro_doc;
if (macro_doc.setContent(&file)) {
QDomElement root = macro_doc.documentElement();
if (root.tagName() == "qet_macro") {
// 1. Unsichtbares Dummy-Projekt erstellen
QScopedPointer<QETProject> dummy_project(new QETProject());
// 2. Bauteile in das Dummy-Projekt laden (wie beim echten Drop)
QDomElement collection_node = root.firstChildElement("collection");
if (!collection_node.isNull()) {
QDomNodeList elements = collection_node.elementsByTagName("element");
for (int i = 0; i < elements.count(); ++i) {
QDomElement elmt_node = elements.at(i).toElement();
QString path = elmt_node.attribute("path");
QDomElement definition = elmt_node.firstChildElement("definition");
if (!path.isEmpty() && !definition.isNull()) {
int last_slash = path.lastIndexOf('/');
QString dir_path = (last_slash != -1) ? path.left(last_slash) : "";
QString file_name = (last_slash != -1) ? path.mid(last_slash + 1) : path;
if (!dir_path.isEmpty()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList parts = dir_path.split('/', QString::SkipEmptyParts);
#else
QStringList parts = dir_path.split('/', Qt::SkipEmptyParts);
#endif
QString current_path = "";
for (const QString &part : parts) {
QString parent_path = current_path;
if (!current_path.isEmpty()) current_path += "/";
current_path += part;
if (current_path == "import") continue;
NamesList empty_names;
dummy_project->embeddedElementCollection()->createDir(parent_path, part, empty_names);
}
}
dummy_project->embeddedElementCollection()->addElementDefinition(dir_path, file_name, definition);
}
}
}
Diagram *dummy_diagram = dummy_project->addNewDiagram();
// 4. Makro auf dem unsichtbaren Blatt zeichnen
QDomElement diagram_content_node = root.firstChildElement("diagram_content");
QDomElement diagram_node = diagram_content_node.firstChildElement("diagram");
if (!diagram_node.isNull()) {
QDomNodeList instances = diagram_node.elementsByTagName("element");
for (int i = 0; i < instances.count(); ++i) {
QDomElement inst = instances.at(i).toElement();
QString type = inst.attribute("type");
if (type.startsWith("macro://")) {
inst.setAttribute("type", type.replace("macro://", "embed://"));
}
}
dummy_diagram->fromXml(diagram_node, QPointF(0, 0), false, nullptr);
dummy_diagram->clearSelection();
// 5. "Screenshot" (Pixmap) von den gezeichneten Elementen machen
QRectF scene_rect = dummy_diagram->itemsBoundingRect();
if (!scene_rect.isEmpty()) {
scene_rect.adjust(-5, -5, 5, 5); // Kleiner Rand
macro_pixmap = QPixmap(scene_rect.size().toSize());
macro_pixmap.fill(Qt::transparent); // Transparenter Hintergrund
QPainter painter(&macro_pixmap);
painter.setRenderHint(QPainter::Antialiasing);
dummy_diagram->render(&painter, macro_pixmap.rect(), scene_rect);
}
}
}
}
}
if (macro_pixmap.isNull()) {
macro_pixmap = QET::Icons::Project.pixmap(32, 32);
}
// Bild verkleinern, falls das Makro gigantisch groß ist
if (macro_pixmap.width() > MAX_DND_PIXMAP_WIDTH || macro_pixmap.height() > MAX_DND_PIXMAP_HEIGHT) {
macro_pixmap = macro_pixmap.scaled(MAX_DND_PIXMAP_WIDTH, MAX_DND_PIXMAP_HEIGHT, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
drag->setPixmap(macro_pixmap);
// Bild zentriert an die Maus hängen
drag->setHotSpot(QPoint(macro_pixmap.width() / 2, macro_pixmap.height() / 2));
}
else if (location.isElement())
{
mime_data->setData("application/x-qet-element-uri",
@@ -93,7 +93,7 @@ QString FileElementCollectionItem::dirPath() const
*/
bool FileElementCollectionItem::isDir() const
{
if (m_path.endsWith(".elmt"))
if (m_path.endsWith(".elmt") || m_path.endsWith(".qetmak"))
return false;
else
return true;
@@ -110,9 +110,9 @@ bool FileElementCollectionItem::isElement() const
}
/**
@brief FileElementCollectionItem::localName
@return the located name of this item
*/
* @brief FileElementCollectionItem::localName
* @return the located name of this item
*/
QString FileElementCollectionItem::localName()
{
if (!text().isNull())
@@ -120,12 +120,17 @@ QString FileElementCollectionItem::localName()
else if (isDir()) {
if (isCollectionRoot()) {
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
if (m_path == QETApp::commonElementsDirN())
setText(QObject::tr("Collection QET"));
else if (m_path == QETApp::companyElementsDirN())
setText(QObject::tr("Collection Company"));
else if (m_path == QETApp::customElementsDirN())
setText(QObject::tr("Collection utilisateur"));
else if (m_path == macrosPath)
setText(QObject::tr("Makros"));
else
setText(QObject::tr("Collection inconnue"));
}
@@ -136,7 +141,7 @@ QString FileElementCollectionItem::localName()
if(docu.load_file(str.toStdString().c_str()))
{
if (QString(docu.document_element().name())
== "qet-directory")
== "qet-directory")
{
NamesList nl;
nl.fromXml(docu.document_element());
@@ -147,7 +152,11 @@ QString FileElementCollectionItem::localName()
}
else if (isElement()) {
ElementsLocation loc(collectionPath());
setText(loc.name());
QString display_name = loc.name();
if (display_name.endsWith(".qetmak")) {
display_name.remove(".qetmak");
}
setText(display_name);
}
return text();
@@ -169,7 +178,11 @@ QString FileElementCollectionItem::localName(const ElementsLocation &location)
localName();
}
else if (isElement()) {
setText(location.name());
QString display_name = location.name();
if (display_name.endsWith(".qetmak")) {
display_name.remove(".qetmak");
}
setText(display_name);
}
return text();
@@ -194,24 +207,29 @@ QString FileElementCollectionItem::name() const
QString FileElementCollectionItem::collectionPath() const
{
if (isCollectionRoot()) {
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
if (m_path == QETApp::commonElementsDirN())
return "common://";
else if (m_path == QETApp::companyElementsDirN())
return "company://";
else
return "custom://";
else if (m_path == macrosPath)
return "macros://"; //
else
return "custom://";
}
else if (parent() && parent()->type()
== FileElementCollectionItem::Type) {
== FileElementCollectionItem::Type) {
ElementCollectionItem *eci =
static_cast<ElementCollectionItem*>(parent());
if (eci->isCollectionRoot())
return eci->collectionPath() + m_path;
static_cast<ElementCollectionItem*>(parent());
if (eci->isCollectionRoot())
return eci->collectionPath() + m_path;
else
return eci->collectionPath() % "/" % m_path;
}
else
return QString();
}
else
return QString();
}
/**
@@ -220,10 +238,14 @@ QString FileElementCollectionItem::collectionPath() const
*/
bool FileElementCollectionItem::isCollectionRoot() const
{
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
if (m_path == QETApp::commonElementsDirN()
|| m_path == QETApp::companyElementsDirN()
|| m_path == QETApp::customElementsDirN())
return true;
|| m_path == QETApp::companyElementsDirN()
|| m_path == QETApp::customElementsDirN()
|| m_path == macrosPath)
return true;
else
return false;
}
@@ -273,55 +295,63 @@ void FileElementCollectionItem::addChildAtPath(const QString &collection_name)
}
/**
@brief FileElementCollectionItem::setUpData
SetUp the data of this item
*/
* @brief FileElementCollectionItem::setUpData
* SetUp the data of this item
*/
void FileElementCollectionItem::setUpData()
{
if (isDir())
{
localName();
setFlags(Qt::ItemIsSelectable
| Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled
| Qt::ItemIsEnabled);
| Qt::ItemIsDragEnabled
| Qt::ItemIsDropEnabled
| Qt::ItemIsEnabled);
}
else
{
setFlags(Qt::ItemIsSelectable
| Qt::ItemIsDragEnabled
| Qt::ItemIsEnabled);
//Set the local name and all informations of the element
//in the data Qt::UserRole+1, these data will be use for search.
ElementsLocation loc(collectionPath());
DiagramContext context = loc.elementInformations();
QStringList search_list;
for (QString& key : context.keys())
{ search_list.append(context.value(key).toString()); }
search_list.append(localName(loc));
setData(search_list.join(" "));
| Qt::ItemIsDragEnabled
| Qt::ItemIsEnabled);
if (m_path.endsWith(".qetmak")) {
setData(localName());
} else {
// Parse standard element information for search
ElementsLocation loc(collectionPath());
DiagramContext context = loc.elementInformations();
QStringList search_list;
for (QString& key : context.keys())
{ search_list.append(context.value(key).toString()); }
search_list.append(localName(loc));
setData(search_list.join(" "));
}
}
setToolTip(collectionPath());
}
/**
@brief FileElementCollectionItem::setUpIcon
SetUp the icon of this item.
Because icon use several memory,
we use this method for setup icon instead setUpData.
*/
* @brief FileElementCollectionItem::setUpIcon
* SetUp the icon of this item.
* Because icon use several memory,
* we use this method for setup icon instead setUpData.
*/
void FileElementCollectionItem::setUpIcon()
{
if (!icon().isNull())
return;
if (isCollectionRoot()) {
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
if (m_path == QETApp::commonElementsDirN())
setIcon(QIcon(":/ico/16x16/qet.png"));
else if (m_path == QETApp::companyElementsDirN())
setIcon(QIcon(":/ico/16x16/go-company.png"));
else if (m_path == macrosPath)
setIcon(QIcon(":/ico/16x16/go-home.png"));
else
setIcon(QIcon(":/ico/16x16/go-home.png"));
}
@@ -330,8 +360,12 @@ void FileElementCollectionItem::setUpIcon()
if (isDir()) {
setIcon(QET::Icons::Folder);
} else {
ElementsLocation loc(collectionPath());
setIcon(loc.icon());
if (m_path.endsWith(".qetmak")) {
setIcon(QIcon());
} else {
ElementsLocation loc(collectionPath());
setIcon(loc.icon());
}
}
}
}
@@ -347,13 +381,13 @@ void FileElementCollectionItem::setUpIcon()
@param hide_element
*/
void FileElementCollectionItem::setPathName(const QString& path_name,
bool set_data,
bool hide_element)
bool set_data,
bool hide_element)
{
m_path = path_name;
//This isn't an element, we create the childs
if (!path_name.endsWith(".elmt"))
//This isn't an element or template, we create the childs
if (!path_name.endsWith(".elmt") && !path_name.endsWith(".qetmak"))
populate(set_data, hide_element);
}
@@ -382,9 +416,9 @@ void FileElementCollectionItem::populate(bool set_data, bool hide_element)
return;
//Get all elmt file in this directory
dir.setNameFilters(QStringList() << "*.elmt");
dir.setNameFilters(QStringList() << "*.elmt" << "*.qetmak");
for (auto& str :
dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name))
dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name))
{
FileElementCollectionItem *feci = new FileElementCollectionItem();
appendRow(feci);
@@ -393,3 +427,15 @@ void FileElementCollectionItem::populate(bool set_data, bool hide_element)
feci->setUpData();
}
}
/**
* @brief FileElementCollectionItem::isMacrosCollection
* @return True if this item represent the macros collection
*/
bool FileElementCollectionItem::isMacrosCollection() const
{
QString macrosPath = QETApp::userMacrosDir();
if (macrosPath.endsWith("/")) macrosPath.remove(macrosPath.length() - 1, 1);
return fileSystemPath().startsWith(macrosPath);
}
@@ -50,6 +50,7 @@ class FileElementCollectionItem : public ElementCollectionItem
bool isCommonCollection() const;
bool isCompanyCollection() const;
bool isCustomCollection() const;
bool isMacrosCollection() const;
void addChildAtPath(const QString &collection_name) override;
void setUpData() override;
@@ -0,0 +1,257 @@
/*
* Copyright 2006-2026 The QElectroTech Team
* This file is part of QElectroTech.
*/
#include "diagrameventaddmacro.h"
#include "../diagram.h"
#include "../qetapp.h"
#include "../qetdiagrameditor.h"
#include "../qetproject.h"
#include "../ElementsCollection/xmlelementcollection.h"
#include "../NameList/nameslist.h"
#include "../diagramcommands.h"
#include "../diagramcontent.h"
#include <QFile>
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include <QStatusBar>
#include <QPainter>
DiagramEventAddMacro::DiagramEventAddMacro(const ElementsLocation &location, Diagram *diagram, QPointF pos) :
DiagramEventInterface(diagram),
m_location(location),
m_preview_item(nullptr)
{
if (loadMacro()) {
init();
QScopedPointer<QETProject> dummy_project(new QETProject());
QDomElement root = m_macro_doc.documentElement();
QDomElement collection_node = root.firstChildElement("collection");
if (!collection_node.isNull()) {
QDomNodeList elements = collection_node.elementsByTagName("element");
for (int i = 0; i < elements.count(); ++i) {
QDomElement elmt_node = elements.at(i).toElement();
QString path = elmt_node.attribute("path");
QDomElement definition = elmt_node.firstChildElement("definition");
if (!path.isEmpty() && !definition.isNull()) {
int last_slash = path.lastIndexOf('/');
QString dir_path = (last_slash != -1) ? path.left(last_slash) : "";
QString file_name = (last_slash != -1) ? path.mid(last_slash + 1) : path;
if (!dir_path.isEmpty()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList parts = dir_path.split('/', QString::SkipEmptyParts);
#else
QStringList parts = dir_path.split('/', Qt::SkipEmptyParts);
#endif
QString current_path = "";
for (const QString &part : parts) {
QString parent_path = current_path;
if (!current_path.isEmpty()) current_path += "/";
current_path += part;
if (current_path == "import") continue;
NamesList empty_names;
dummy_project->embeddedElementCollection()->createDir(parent_path, part, empty_names);
}
}
dummy_project->embeddedElementCollection()->addElementDefinition(dir_path, file_name, definition);
}
}
}
Diagram *dummy_diagram = dummy_project->addNewDiagram();
QDomElement diagram_node = root.firstChildElement("diagram_content").firstChildElement("diagram");
if (!diagram_node.isNull()) {
dummy_diagram->fromXml(diagram_node, QPointF(0, 0), false, nullptr);
QRectF scene_rect = dummy_diagram->itemsBoundingRect();
if (!scene_rect.isEmpty()) {
QPixmap pixmap(scene_rect.toAlignedRect().size());
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing);
dummy_diagram->render(&painter, QRectF(QPointF(0,0), scene_rect.size()), scene_rect);
m_preview_item = new QGraphicsPixmapItem(pixmap);
m_preview_item->setOffset(scene_rect.topLeft());
}
}
if (m_preview_item) {
m_preview_item->setPos(Diagram::snapToGrid(pos));
m_preview_item->setOpacity(0.6);
m_diagram->addItem(m_preview_item);
m_running = true;
}
if (!diagram->views().isEmpty()) {
const auto qde = QETApp::diagramEditorAncestorOf(diagram->views().at(0));
if (qde) {
m_status_bar = qde->statusBar();
}
} else {
m_status_bar.clear();
}
}
}
DiagramEventAddMacro::~DiagramEventAddMacro()
{
if (m_preview_item) {
m_diagram->removeItem(m_preview_item);
delete m_preview_item;
}
if (m_status_bar) {
m_status_bar->clearMessage();
}
for (auto view : m_diagram->views())
view->setContextMenuPolicy(Qt::DefaultContextMenu);
}
void DiagramEventAddMacro::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (m_preview_item) {
const auto pos_{Diagram::snapToGrid(event->scenePos())};
m_preview_item->setPos(pos_);
if (m_status_bar) {
m_status_bar->showMessage(QString("x %1 : y %2 (Makro-Anker)").arg(QString::number(pos_.x()), QString::number(pos_.y())));
}
}
event->setAccepted(true);
}
void DiagramEventAddMacro::mousePressEvent(QGraphicsSceneMouseEvent *event) {
event->setAccepted(true);
}
void DiagramEventAddMacro::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (m_preview_item) {
if (event->button() == Qt::RightButton) {
m_diagram->removeItem(m_preview_item);
delete m_preview_item;
m_preview_item = nullptr;
m_running = false;
emit finish();
}
else if (event->button() == Qt::LeftButton) {
addMacro(Diagram::snapToGrid(event->scenePos()));
}
}
event->setAccepted(true);
}
void DiagramEventAddMacro::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
if (m_preview_item && (event->button() == Qt::LeftButton)) {
m_diagram->removeItem(m_preview_item);
delete m_preview_item;
m_preview_item = nullptr;
m_running = false;
emit finish();
}
event->setAccepted(true);
}
void DiagramEventAddMacro::keyPressEvent(QKeyEvent *event)
{
DiagramEventInterface::keyPressEvent(event);
}
void DiagramEventAddMacro::init()
{
foreach(QGraphicsView *view, m_diagram->views())
view->setContextMenuPolicy(Qt::NoContextMenu);
}
bool DiagramEventAddMacro::loadMacro()
{
QFile file(m_location.fileSystemPath());
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Error: Macro file could not be read:" << m_location.fileSystemPath();
return false;
}
if (!m_macro_doc.setContent(&file)) {
qDebug() << "Error: Invalid XML in macro.";
return false;
}
QDomElement root = m_macro_doc.documentElement();
if (root.tagName() != "qet_macro") return false;
QDomElement collection_node = root.firstChildElement("collection");
if (!collection_node.isNull()) {
QDomNodeList elements = collection_node.elementsByTagName("element");
for (int i = 0; i < elements.count(); ++i) {
QDomElement elmt_node = elements.at(i).toElement();
QString path = elmt_node.attribute("path");
QDomElement definition = elmt_node.firstChildElement("definition");
if (!path.isEmpty() && !definition.isNull()) {
int last_slash = path.lastIndexOf('/');
QString dir_path = (last_slash != -1) ? path.left(last_slash) : "";
QString file_name = (last_slash != -1) ? path.mid(last_slash + 1) : path;
if (!dir_path.isEmpty()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList parts = dir_path.split('/', QString::SkipEmptyParts);
#else
QStringList parts = dir_path.split('/', Qt::SkipEmptyParts);
#endif
QString current_path = "";
for (const QString &part : parts) {
QString parent_path = current_path;
if (!current_path.isEmpty()) current_path += "/";
current_path += part;
if (current_path == "import") continue;
NamesList empty_names;
m_diagram->project()->embeddedElementCollection()->createDir(parent_path, part, empty_names);
}
}
m_diagram->project()->embeddedElementCollection()->addElementDefinition(dir_path, file_name, definition);
}
}
}
QDomElement diagram_node = root.firstChildElement("diagram_content").firstChildElement("diagram");
if (!diagram_node.isNull()) {
QDomNodeList instances = diagram_node.elementsByTagName("element");
for (int i = 0; i < instances.count(); ++i) {
QDomElement inst = instances.at(i).toElement();
QString type = inst.attribute("type");
if (type.startsWith("macro://")) {
inst.setAttribute("type", type.replace("macro://", "embed://"));
}
}
}
return true;
}
void DiagramEventAddMacro::addMacro(QPointF final_pos)
{
QDomElement root = m_macro_doc.documentElement();
QDomElement diagram_node = root.firstChildElement("diagram_content").firstChildElement("diagram");
if (!diagram_node.isNull()) {
QDomElement cloned_node = diagram_node.cloneNode(true).toElement();
QPointF target_pos = final_pos;
DiagramContent pasted_content;
m_diagram->fromXml(cloned_node, target_pos, false, &pasted_content);
m_diagram->refreshContents();
m_diagram->undoStack().push(new PasteDiagramCommand(m_diagram, pasted_content));
}
}
@@ -0,0 +1,45 @@
/*
C opyright 2006-2026 The QEle*ctroTech Team
This file is part of QElectroTech.
*/
#ifndef DIAGRAMEVENTADDMACRO_H
#define DIAGRAMEVENTADDMACRO_H
#include "../ElementsCollection/elementslocation.h"
#include "diagrameventinterface.h"
#include <QDomDocument>
#include <QGraphicsPixmapItem>
class QStatusBar;
/**
* @brief The DiagramEventAddMacro class
*/
class DiagramEventAddMacro : public DiagramEventInterface
{
Q_OBJECT
public:
DiagramEventAddMacro(const ElementsLocation &location, Diagram *diagram, QPointF pos = QPointF(0,0));
~DiagramEventAddMacro() override;
void mouseMoveEvent (QGraphicsSceneMouseEvent *event) override;
void mousePressEvent (QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override;
void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override;
void keyPressEvent (QKeyEvent *event) override;
void init() override;
private:
bool loadMacro();
void addMacro(QPointF final_pos);
private:
ElementsLocation m_location;
QDomDocument m_macro_doc;
QGraphicsPixmapItem *m_preview_item;
QPointer<QStatusBar> m_status_bar;
};
#endif // DIAGRAMEVENTADDMACRO_H
+122 -19
View File
@@ -20,6 +20,7 @@
#include "QPropertyUndoCommand/qpropertyundocommand.h"
#include "diagramcommands.h"
#include "diagramevent/diagrameventaddelement.h"
#include "diagramevent/diagrameventaddmacro.h"
#include "dvevent/dveventinterface.h"
#include "projectview.h"
#include "qetdiagrameditor.h"
@@ -34,7 +35,9 @@
#include "utils/conductorcreator.h"
#include "undocommand/addgraphicsobjectcommand.h"
#include "diagram.h"
#include "ElementsCollection/xmlelementcollection.h"
#include "NameList/nameslist.h"
#include "elementdialog.h"
#include <QDropEvent>
/**
@@ -84,6 +87,10 @@ DiagramView::DiagramView(Diagram *diagram, QWidget *parent) :
d.exec();
});
// Setup the action to create a template
m_create_template = new QAction(tr("Créer un template", "context menu action"), this);
connect(m_create_template, SIGNAL(triggered()), this, SLOT(createTemplateFromSelection()));
//setup three separators, to be use in context menu
for(int i=0 ; i<3 ; ++i)
{
@@ -188,13 +195,13 @@ void DiagramView::dropEvent(QDropEvent *e) {
}
/**
@brief DiagramView::handleElementDrop
Handle the drop of an element.
@param event the QDropEvent describing the current drag'n drop
*/
* @brief DiagramView::handleElementDrop
* Handle the drop of an element.
* @param event the QDropEvent describing the current drag'n drop
*/
void DiagramView::handleElementDrop(QDropEvent *event)
{
//Build an element from the text of the mime data
//Build an element from the text of the mime data
ElementsLocation location(event->mimeData()->text());
if ( !(location.isElement() && location.exist()) )
@@ -203,20 +210,20 @@ void DiagramView::handleElementDrop(QDropEvent *event)
return;
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
diagram()->setEventInterface(
new DiagramEventAddElement(
location, diagram(), mapToScene(event->pos())));
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 6 or later")
#endif
diagram()->setEventInterface(
new DiagramEventAddElement(
location, diagram(), event->position()));
#endif
QPointF drop_pos;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
drop_pos = mapToScene(event->pos());
#else
drop_pos = event->position();
#endif
//Set focus to the view to get event
if (location.path().endsWith(".qetmak")) {
diagram()->setEventInterface(new DiagramEventAddMacro(location, diagram(), drop_pos));
} else {
diagram()->setEventInterface(new DiagramEventAddElement(location, diagram(), drop_pos));
}
//Set focus to the view to get event
this->setFocus();
}
@@ -1202,6 +1209,7 @@ QList<QAction *> DiagramView::contextMenuActions() const
list << qde->m_copy;
list << m_multi_paste;
list << m_separators.at(0);
list << m_create_template; // Add the create template action
list << qde->m_conductor_reset;
list << m_separators.at(1);
list << qde->m_selection_actions_group.actions();
@@ -1265,6 +1273,101 @@ void DiagramView::contextMenuEvent(QContextMenuEvent *e)
}
}
/**
* @brief DiagramView::createTemplateFromSelection
* Triggered from the context menu to create a new template (macro) from the current selection.
*/
void DiagramView::createTemplateFromSelection()
{
QList<QGraphicsItem *> selected_elements = m_diagram->selectedItems();
if (selected_elements.isEmpty()) {
return;
}
qDebug() << "Ready to create a template from" << selected_elements.size() << "elements!";
// Open the dialog to let the user select where to save the .qetmak file
ElementsLocation template_location = ElementDialog::getSaveTemplateLocation(this);
// Check if the user clicked 'Cancel' or closed the window
if (template_location.isNull()) {
qDebug() << "User canceled template creation.";
return;
}
qDebug() << "Will save template to:" << template_location.path();
QDomDocument content_xml = m_diagram->toXml(false, true);
QDomDocument macro_doc;
QDomElement root = macro_doc.createElement("qet_macro");
macro_doc.appendChild(root);
QDomElement collection_node = macro_doc.createElement("collection");
root.appendChild(collection_node);
QSet<QString> processed_types;
QDomNodeList element_nodes = content_xml.elementsByTagName("element");
for (int i = 0; i < element_nodes.count(); ++i) {
QDomElement elmt_node = element_nodes.at(i).toElement();
QString old_type = elmt_node.attribute("type");
if (old_type.isEmpty()) continue;
ElementsLocation loc(old_type, m_diagram->project());
QString clean_path = loc.collectionPath(false);
QString new_type = "macro://" + clean_path;
elmt_node.setAttribute("type", new_type);
if (!processed_types.contains(clean_path)) {
processed_types.insert(clean_path);
QDomElement definition_node = loc.xml();
if (!definition_node.isNull()) {
QDomElement collection_elmt = macro_doc.createElement("element");
collection_elmt.setAttribute("path", clean_path);
QDomNode imported_def = macro_doc.importNode(definition_node, true);
collection_elmt.appendChild(imported_def);
collection_node.appendChild(collection_elmt);
} else {
qDebug() << "Warnung: Konnte XML-Definition für" << old_type << "nicht laden.";
}
}
}
QDomElement content_container = macro_doc.createElement("diagram_content");
root.appendChild(content_container);
QDomNode imported_node = macro_doc.importNode(content_xml.documentElement(), true);
content_container.appendChild(imported_node);
QString full_path = template_location.fileSystemPath();
QDir().mkpath(QFileInfo(full_path).absolutePath());
QFile file(full_path);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out.setCodec("UTF-8");
out << macro_doc.toString(4);
file.close();
qDebug() << "Template successfully saved to:" << full_path;
QMessageBox::information(this, tr("Modèle enregistré"),
tr("Le modèle a été enregistré avec succès sous :\n%1").arg(full_path));
} else {
qDebug() << "Error: Could not open file for writing:" << full_path;
QMessageBox::critical(this, tr("Erreur"), tr("Le fichier n'a pas pu être écrit."));
}
}
/**
@return l'editeur de schemas parent ou 0
*/
+3 -1
View File
@@ -18,7 +18,7 @@
#ifndef DIAGRAMVIEW_H
#define DIAGRAMVIEW_H
#include "ElementsCollection/elementslocation.h"
#include "../ElementsCollection/elementslocation.h"
#include "titleblock/templatelocation.h"
#include <QClipboard>
@@ -53,6 +53,7 @@ class DiagramView : public QGraphicsView
DVEventInterface *m_event_interface = nullptr;
QAction *m_paste_here = nullptr;
QAction *m_multi_paste = nullptr;
QAction *m_create_template = nullptr;
QPoint m_paste_here_pos;
QPointF m_drag_last_pos;
bool m_fresh_focus_in,
@@ -133,5 +134,6 @@ class DiagramView : public QGraphicsView
private slots:
void adjustGridToZoom();
void applyReadOnly();
void createTemplateFromSelection();
};
#endif
@@ -1,4 +1,4 @@
/*
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
@@ -96,8 +96,18 @@ void ElementPropertiesEditorWidget::upDateInterface()
}
else if (m_data.m_type == ElementData::Master) {
ui->m_master_type_cb->setCurrentIndex(
ui->m_master_type_cb->findData (
m_data.m_master_type));
ui->m_master_type_cb->findData (
m_data.m_master_type));
// NEU: Checkbox und Zahlenbox für max_slaves einstellen
if (m_data.m_max_slaves == -1) {
ui->max_slaves_checkbox->setChecked(false);
ui->max_slaves_spinbox->setEnabled(false);
} else {
ui->max_slaves_checkbox->setChecked(true);
ui->max_slaves_spinbox->setEnabled(true);
ui->max_slaves_spinbox->setValue(m_data.m_max_slaves);
}
} else if (m_data.m_type == ElementData::Terminal) {
ui->m_terminal_type_cb->setCurrentIndex(
ui->m_terminal_type_cb->findData(
@@ -151,10 +161,13 @@ void ElementPropertiesEditorWidget::setUpInterface()
ui->m_terminal_func_cb->addItem(tr("Phase"), ElementData::TFPhase);
ui->m_terminal_func_cb->addItem(tr("Neutre"), ElementData::TFNeutral);
//Disable the edition of the first column of the information tree
//by this little workaround
//Disable the edition of the first column of the information tree
//by this little workaround
ui->m_tree->setItemDelegate(new EditorDelegate(this));
ui->m_tree->header()->resizeSection(0, 150);
// NEU: Checkbox mit der Zahlenbox verbinden (Aktivieren/Deaktivieren)
connect(ui->max_slaves_checkbox, SIGNAL(toggled(bool)), ui->max_slaves_spinbox, SLOT(setEnabled(bool)));
populateTree();
}
@@ -226,6 +239,13 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
}
else if (m_data.m_type == ElementData::Master) {
m_data.m_master_type = ui->m_master_type_cb->currentData().value<ElementData::MasterType>();
//If the checkbox is checked, save the number; otherwise, -1 (infinity)
if (ui->max_slaves_checkbox->isChecked()) {
m_data.m_max_slaves = ui->max_slaves_spinbox->value();
} else {
m_data.m_max_slaves = -1;
}
}
else if (m_data.m_type == ElementData::Terminal)
{
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>527</width>
<height>442</height>
<height>492</height>
</rect>
</property>
<property name="windowTitle">
@@ -104,6 +104,23 @@
<item row="0" column="1">
<widget class="QComboBox" name="m_master_type_cb"/>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="max_slaves_checkbox">
<property name="text">
<string>Définir le nombre maximal d'esclaves</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="max_slaves_spinbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
+54 -20
View File
@@ -74,6 +74,10 @@ void ElementDialog::setUpWidget()
title_ = tr("Enregistrer une catégorie", "dialog title");
label_ = tr("Choisissez une catégorie.", "dialog content");
break;
case SaveTemplate:
title_ = tr("Enregistrer un template", "dialog title");
label_ = tr("Choisissez l'emplacement dans lequel vous souhaitez enregistrer votre template.", "dialog content");
break;
default:
title_ = tr("Titre");
label_ = tr("Label");
@@ -92,10 +96,14 @@ void ElementDialog::setUpWidget()
foreach(QETProject *prj, QETApp::registeredProjects())
prjs.append(prj);
if (m_mode == OpenElement)
if (m_mode == OpenElement) {
m_model->loadCollections(true, true, true, prjs);
else
} else if (m_mode == SaveTemplate) {
// Load only the templates/macros collection for the template save dialog
m_model->loadMacrosCollection();
} else {
m_model->loadCollections(false, true, true, prjs);
}
m_tree_view->setModel(m_model);
m_tree_view->setHeaderHidden(true);
@@ -103,14 +111,21 @@ void ElementDialog::setUpWidget()
m_buttons_box = new QDialogButtonBox(this);
if (m_mode == SaveCategory || m_mode == SaveElement)
if (m_mode == SaveCategory || m_mode == SaveElement || m_mode == SaveTemplate)
{
m_buttons_box->setStandardButtons(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
m_buttons_box->button(QDialogButtonBox::Save)->setDisabled(true);
m_text_field = new QFileNameEdit();
m_text_field->setDisabled(true);
m_text_field->setPlaceholderText(m_mode == SaveCategory? tr("Nom du nouveau dossier") : tr("Nom du nouvel élément"));
if (m_mode == SaveCategory) {
m_text_field->setPlaceholderText(tr("Nom du nouveau dossier"));
} else if (m_mode == SaveTemplate) {
m_text_field->setPlaceholderText(tr("Nom du nouveau template"));
} else {
m_text_field->setPlaceholderText(tr("Nom du nouvel élément"));
}
layout->addWidget(m_text_field);
}
@@ -156,14 +171,17 @@ void ElementDialog::checkCurrentLocation()
if (m_mode == OpenElement) {
m_buttons_box->button(QDialogButtonBox::Open)->setEnabled(m_location.isElement() && m_location.exist());
}
else if (m_mode == SaveElement)
else if (m_mode == SaveElement || m_mode == SaveTemplate)
{
m_buttons_box->button(QDialogButtonBox::Save)->setDisabled(true);
//Location doesn't exist
//Location doesn't exist
if (!m_location.exist()) { return; }
if (m_location.isElement())
// Accept .elmt for elements, and .qetmak for templates
bool is_valid_file = m_location.isElement() || (m_mode == SaveTemplate && m_location.path().endsWith(".qetmak"));
if (is_valid_file)
{
m_text_field->setDisabled(true);
m_buttons_box->button(QDialogButtonBox::Save)->setEnabled(true);
@@ -174,10 +192,10 @@ void ElementDialog::checkCurrentLocation()
if (m_text_field->text().isEmpty()) { return; }
//Only enable save button if the location at path :
//m_location.collectionPath + m_text_filed.text doesn't exist.
//Only enable save button if the location at path doesn't exist.
QString new_path = m_text_field->text();
if (!new_path.endsWith(".elmt")) new_path += ".elmt";
QString extension = (m_mode == SaveTemplate) ? ".qetmak" : ".elmt";
if (!new_path.endsWith(extension)) new_path += extension;
ElementsLocation loc = m_location;
loc.addToPath(new_path);
@@ -209,15 +227,19 @@ void ElementDialog::checkAccept()
return;
}
}
else if (m_mode == SaveElement)
else if (m_mode == SaveElement || m_mode == SaveTemplate)
{
if (loc.isElement())
bool is_valid_file = loc.isElement() || (m_mode == SaveTemplate && loc.path().endsWith(".qetmak"));
if (is_valid_file)
{
if (loc.exist())
{
QString msgTitle = (m_mode == SaveTemplate) ? tr("Écraser le template ?", "message box title") : tr("Écraser l'élément ?", "message box title");
QString msgContent = (m_mode == SaveTemplate) ? tr("Le template existe déjà. Voulez-vous l'écraser ?", "message box content") : tr("L'élément existe déjà. Voulez-vous l'écraser ?", "message box content");
QMessageBox::StandardButton answer = QET::QetMessageBox::question(this,
tr("Écraser l'élément ?", "message box title"),
tr("L'élément existe déjà. Voulez-vous l'écraser ?", "message box content"),
msgTitle,
msgContent,
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::Yes) {accept();}
@@ -248,19 +270,21 @@ ElementsLocation ElementDialog::location() const
else {return ElementsLocation(); }
}
else if (m_mode == SaveElement)
else if (m_mode == SaveElement || m_mode == SaveTemplate)
{
//Current selected location is element, we return this location
if (m_location.isElement()) { return m_location; }
//Current selected location is element or template, we return this location
bool is_valid_file = m_location.isElement() || (m_mode == SaveTemplate && m_location.path().endsWith(".qetmak"));
if (is_valid_file) { return m_location; }
//Current selected location is directory, we return a location at path :
//m_location->collectionPath + m_text_field->text
//Current selected location is directory, we return a location at path :
//m_location->collectionPath + m_text_field->text
else if (m_location.isDirectory())
{
QString new_path = m_text_field->text();
if (new_path.isEmpty()) { return ElementsLocation(); }
if (!new_path.endsWith(".elmt")) { new_path += ".elmt"; }
QString extension = (m_mode == SaveTemplate) ? ".qetmak" : ".elmt";
if (!new_path.endsWith(extension)) { new_path += extension; }
ElementsLocation loc = m_location;
loc.addToPath(new_path);
@@ -291,6 +315,16 @@ ElementsLocation ElementDialog::getSaveElementLocation(QWidget *parentWidget) {
return(ElementDialog::execConfiguredDialog(ElementDialog::SaveElement, parentWidget));
}
/**
* @brief ElementDialog::getSaveTemplateLocation
* Display a dialog that allow to user to select a location for saving a template
* @param parentWidget
* @return The location where the template must be save
*/
ElementsLocation ElementDialog::getSaveTemplateLocation(QWidget *parentWidget) {
return(ElementDialog::execConfiguredDialog(ElementDialog::SaveTemplate, parentWidget));
}
/**
@brief ElementDialog::execConfiguredDialog
launch a dialog with the chosen mode
+3 -1
View File
@@ -42,7 +42,8 @@ class ElementDialog : public QDialog
OpenElement = 0, ///< The dialog should open an element
SaveElement = 1, ///< The dialog should select an element for saving
OpenCategory = 2, ///< The dialog should open a category
SaveCategory = 3 ///< The dialog should select a category for saving
SaveCategory = 3, ///< The dialog should select a category for saving
SaveTemplate = 4 ///< The dialog should select a template for saving
};
// constructors, destructor
@@ -74,6 +75,7 @@ class ElementDialog : public QDialog
public:
static ElementsLocation getOpenElementLocation(QWidget *parent = nullptr);
static ElementsLocation getSaveElementLocation(QWidget *parent = nullptr);
static ElementsLocation getSaveTemplateLocation(QWidget *parent = nullptr);
private:
static ElementsLocation execConfiguredDialog(int, QWidget *parent = nullptr);
+95 -13
View File
@@ -67,7 +67,10 @@ ElementsPanel::ElementsPanel(QWidget *parent) :
connect(this, &ElementsPanel::itemDoubleClicked, this, &ElementsPanel::slot_doubleClick);
connect(this, &GenericPanel::firstActivated, [this]() {QTimer::singleShot(250, this, SLOT(reload()));});
connect(this, &ElementsPanel::panelContentChanged, this, &ElementsPanel::panelContentChange);
// manage signal itemClicked
connect(this, &ElementsPanel::itemClicked, this, &ElementsPanel::slot_clicked);
//Emit a signal instead au manage is own context menu
setContextMenuPolicy(Qt::CustomContextMenu);
}
@@ -139,15 +142,26 @@ QTreeWidgetItem *ElementsPanel::addProject(QETProject *project,
Q_UNUSED(options)
bool first_add = (first_reload_ || !projects_to_display_.contains(project));
clearSelection();
// create the QTreeWidgetItem representing the project
// create the QTreeWidgetItem representing the project
QTreeWidgetItem *qtwi_project = GenericPanel::addProject(project, nullptr, GenericPanel::All);
// the project will be inserted right before the common tb templates collection
// the project will be inserted right before the common tb templates collection
invisibleRootItem() -> insertChild(
indexOfTopLevelItem(common_tbt_collection_item_),
qtwi_project
);
if (first_add) qtwi_project -> setExpanded(true);
if (first_add){
qtwi_project -> setExpanded(true);
// on adding an project select first diagram
setCurrentItem(qtwi_project -> child(0));
qtwi_project -> child(0)->setSelected(true);
}
else {
// on adding an diagram to project select the last diagram
setCurrentItem(qtwi_project->child(qtwi_project->childCount()-2));
qtwi_project->child(qtwi_project->childCount()-2)->setSelected(true);
}
if (TitleBlockTemplatesCollection *tbt_collection = project -> embeddedTitleBlockTemplatesCollection()) {
if (QTreeWidgetItem *tbt_collection_qtwi = itemForTemplatesCollection(tbt_collection)) {
@@ -258,21 +272,28 @@ void ElementsPanel::reload()
}
/**
Gere le double-clic sur un element.
Si un double-clic sur un projet est effectue, le signal requestForProject
est emis.
Si un double-clic sur un schema est effectue, le signal requestForDiagram
est emis.
@brief ElementsPanel::slot_clicked
handle click on qtwi
@param qtwi item that was clickerd on
*/
void ElementsPanel::slot_clicked(QTreeWidgetItem *clickedItem, int) {
requestForItem(clickedItem);
}
/**
@brief ElementsPanel::slot_doubleClick
handle double click on qtwi
@param qtwi
*/
void ElementsPanel::slot_doubleClick(QTreeWidgetItem *qtwi, int) {
int qtwi_type = qtwi -> type();
if (qtwi_type == QET::Project) {
QETProject *project = valueForItem<QETProject *>(qtwi);
emit(requestForProject(project));
// open project properties
emit(requestForProjectPropertiesEdition());
} else if (qtwi_type == QET::Diagram) {
Diagram *diagram = valueForItem<Diagram *>(qtwi);
diagram->showMe();
// open diagram properties
emit(requestForDiagramPropertiesEdition());
} else if (qtwi_type == QET::TitleBlockTemplate) {
TitleBlockTemplateLocation tbt = valueForItem<TitleBlockTemplateLocation>(qtwi);
emit(requestForTitleBlockTemplate(tbt));
@@ -444,3 +465,64 @@ void ElementsPanel::ensureHierarchyIsVisible(const QList<QTreeWidgetItem *> &ite
if (parent_qtwi -> isHidden()) parent_qtwi -> setHidden(false);
}
}
/**
* @brief ElementsPanel::syncTabBars
* set the project- or diagram Tab corresponding to
* the selection in the treeView
*/
void ElementsPanel::requestForItem(QTreeWidgetItem *clickedItem)
{
// activate diagram
if(clickedItem->type() == QET::Diagram){
Diagram *diagram = valueForItem<Diagram *>(clickedItem);
// if we click on diagramItem in annother project we need the other project
emit(requestForProject(projectForItem(clickedItem->parent())));
// required for keyPressEvent
// after emit the focus is on the diagram editor, we put it back to elementsPanel
this->setFocus();
// activate diagram
diagram->showMe();
}
// activate project
else if(clickedItem->type() == QET::Project) {
QETProject *project = projectForItem(clickedItem);
emit(requestForProject(project));
this->setFocus();
}
}
/**
* @brief ElementsPanel::keyPressEvent
* @param event
*/
void ElementsPanel::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_Up:{
// check if there is another item abbove
if(!itemAbove(currentItem()))
break;
setCurrentItem(itemAbove(currentItem()));
if (currentItem()->type()==QET::Diagram || currentItem()->type()==QET::Project){
requestForItem(currentItem());
}
break;
}
case Qt::Key_Down:{
// check if there is another item below
if(!itemBelow(currentItem()))
break;
setCurrentItem(itemBelow(currentItem()));
if (currentItem()->type()==QET::Diagram || currentItem()->type()==QET::Project){
requestForItem(currentItem());
}
break;
}
default:
QTreeView::keyPressEvent(event);
}
}
+9 -2
View File
@@ -53,8 +53,13 @@ class ElementsPanel : public GenericPanel {
signals:
void requestForProject(QETProject *);
void requestForTitleBlockTemplate(const TitleBlockTemplateLocation &);
// Signal to open the project properties
void requestForProjectPropertiesEdition();
// Signal to open the diagram properties
void requestForDiagramPropertiesEdition();
public slots:
void slot_clicked(QTreeWidgetItem *, int);
void slot_doubleClick(QTreeWidgetItem *, int);
void reload();
void filter(const QString &, QET::Filtering = QET::RegularFilter);
@@ -63,7 +68,9 @@ class ElementsPanel : public GenericPanel {
void buildFilterList();
void applyCurrentFilter(const QList<QTreeWidgetItem *> &);
void ensureHierarchyIsVisible(const QList<QTreeWidgetItem *> &);
void requestForItem(QTreeWidgetItem *);
void keyPressEvent(QKeyEvent *event)override;
protected:
void startDrag(Qt::DropActions) override;
void startTitleBlockTemplateDrag(const TitleBlockTemplateLocation &);
+20
View File
@@ -24,6 +24,7 @@
#include "qeticons.h"
#include "qetproject.h"
#include "titleblock/templatedeleter.h"
#include <QFileInfo>
/*
When the ENABLE_PANEL_WIDGET_DND_CHECKS flag is set, the panel
@@ -120,6 +121,12 @@ ElementsPanelWidget::ElementsPanelWidget(QWidget *parent) : QWidget(parent) {
SLOT(openTitleBlockTemplate(const TitleBlockTemplateLocation &))
);
// manage double click on TreeWidgetItem
connect(elements_panel, SIGNAL(requestForProjectPropertiesEdition()), this, SLOT(editProjectProperties()) );
connect(elements_panel, SIGNAL(requestForDiagramPropertiesEdition()), this, SLOT(editDiagramProperties()) );
// manage project activation
connect(elements_panel, SIGNAL(requestForProject(QETProject*)), this, SIGNAL(requestForProject(QETProject*)));
// disposition verticale
QVBoxLayout *vlayout = new QVBoxLayout(this);
vlayout -> setContentsMargins(0,0,0,0);
@@ -146,6 +153,11 @@ void ElementsPanelWidget::openDirectoryForSelectedItem()
if (QTreeWidgetItem *qtwi = elements_panel -> currentItem()) {
QString dir_path = elements_panel -> dirPathForItem(qtwi);
if (!dir_path.isEmpty()) {
QFileInfo fileInfo(dir_path);
// Wenn der Pfad auf eine Datei (z.B. Makro) zeigt, isoliere den Ordnerpfad
if (fileInfo.isFile()) {
dir_path = fileInfo.absolutePath();
}
QDesktopServices::openUrl(QUrl::fromLocalFile(dir_path));
}
}
@@ -236,6 +248,7 @@ void ElementsPanelWidget::deleteDiagram()
{
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
emit(requestForDiagramDeletion(selected_diagram));
elements_panel->reload();
}
}
@@ -473,28 +486,33 @@ void ElementsPanelWidget::keyPressEvent (QKeyEvent *e) {
break;
case Qt::Key_F3:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveUp(selected_diagram));
}
break;
case Qt::Key_F4:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveDown(selected_diagram));
}
break;
case Qt::Key_F5:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveUpTop(selected_diagram));
}
break;
case Qt::Key_F6:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveDownx10(selected_diagram));
}
break;
case Qt::Key_F7:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveDownx100(selected_diagram));
}
@@ -502,12 +520,14 @@ void ElementsPanelWidget::keyPressEvent (QKeyEvent *e) {
break;
case Qt::Key_F8:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveUpx10(selected_diagram));
}
break;
case Qt::Key_F9:
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
elements_panel->setSelectedItem(elements_panel->getItemForDiagram(selected_diagram));
emit(requestForDiagramMoveUpx100(selected_diagram));
}
break;
+2 -1
View File
@@ -418,7 +418,8 @@ void ExportDialog::generateSvg(
// "joue" la QPicture sur un QSvgGenerator
QSvgGenerator svg_engine;
svg_engine.setSize(QSize((width*9/16), (height*9/16)));
svg_engine.setSize(QSize(width, height));
svg_engine.setViewBox(QRect(0, 0, width*0.75, height*0.75));
svg_engine.setOutputDevice(&io_device);
QPainter svg_painter(&svg_engine);
picture.play(&svg_painter);
+16 -2
View File
@@ -766,7 +766,6 @@ void GenericPanel::projectDiagramsOrderChanged(QETProject *project,
if (!moved_qtwi_diagram) return;
// remove the QTWI then insert it back at the adequate location
bool was_selected = moved_qtwi_diagram -> isSelected();
qtwi_project -> removeChild (moved_qtwi_diagram);
qtwi_project -> insertChild (to, moved_qtwi_diagram);
@@ -781,8 +780,14 @@ void GenericPanel::projectDiagramsOrderChanged(QETProject *project,
updateDiagramItem(qtwi_diagram, diagram);
}
if (was_selected)
// select the moved diagram
if(m_selected_item){
setCurrentItem(moved_qtwi_diagram);
}
else{
setCurrentItem(qtwi_project -> child(from));
}
m_selected_item = nullptr;
emit(panelContentChanged());
}
@@ -1041,3 +1046,12 @@ void GenericPanel::emitFirstActivated()
{
emit(firstActivated());
}
/**
@brief GenericPanel::setSelectedItem
@param selectedItem
*/
void GenericPanel::setSelectedItem(QTreeWidgetItem *selectedItem)
{
m_selected_item = selectedItem;
}
+6 -1
View File
@@ -95,8 +95,8 @@ class GenericPanel : public QTreeWidget {
virtual QTreeWidgetItem *addDiagram(Diagram *,
QTreeWidgetItem * = nullptr,
PanelOptions = AddAllChild);
protected:
virtual QTreeWidgetItem *getItemForDiagram(Diagram *, bool * = nullptr);
protected:
virtual QTreeWidgetItem *updateDiagramItem(QTreeWidgetItem *,
Diagram *,
PanelOptions = AddAllChild,
@@ -171,6 +171,9 @@ class GenericPanel : public QTreeWidget {
const QString &);
// various other methods
public:
void setSelectedItem(QTreeWidgetItem *selectedItem);
protected:
virtual QString defaultText(QET::ItemType);
virtual QIcon defaultIcon(QET::ItemType);
@@ -222,5 +225,7 @@ class GenericPanel : public QTreeWidget {
representing a title block template
*/
QHash<TitleBlockTemplateLocation, QTreeWidgetItem *> tb_templates_;
QTreeWidgetItem *m_selected_item = nullptr;
};
#endif
+57 -18
View File
@@ -721,6 +721,14 @@ void ProjectView::initActions()
m_end_view = new QAction(QET::Icons::ArrowRightDouble, tr("Aller à la fin du projet"),this);
connect(m_end_view, &QAction::triggered, [this](){this->m_tab->setCurrentWidget(lastDiagram());});
// button to scroll one page left
m_next_view_left = new QAction(QET::Icons::ArrowLeft, tr("go one page left"),this);
connect(m_next_view_left, &QAction::triggered, [this](){this->m_tab->setCurrentWidget(previousDiagram());});
// button to scroll one page right
m_next_view_right = new QAction(QET::Icons::ArrowRight, tr("go one page right"),this);
connect(m_next_view_right, &QAction::triggered, [this](){this->m_tab->setCurrentWidget(nextDiagram());});
}
/**
@@ -748,34 +756,65 @@ void ProjectView::initWidgets()
m_tab = new QTabWidget(this);
#endif
m_tab -> setMovable(true);
// setting UsesScrollButton ensures that when the tab bar is full, the tabs are scrolled.
m_tab -> setUsesScrollButtons(true);
// disable the internal scroll buttons of the TabWidget, we will use our own buttons.
m_tab->setStyleSheet("QTabBar QToolButton {border-image: ;border-width: 0px}");
m_tab->setStyleSheet("QTabBar::scroller {width: 0px;}");
// add layouts
QHBoxLayout *TopRightCorner_Layout = new QHBoxLayout();
TopRightCorner_Layout->setContentsMargins(0,0,0,0);
// some place left to the 'next_right_view_button' button
TopRightCorner_Layout->insertSpacing(1,10);
QToolButton *add_new_diagram_button = new QToolButton;
add_new_diagram_button -> setDefaultAction(m_add_new_diagram);
add_new_diagram_button -> setAutoRaise(true);
TopRightCorner_Layout->addWidget(add_new_diagram_button);
QHBoxLayout *TopLeftCorner_Layout = new QHBoxLayout();
TopLeftCorner_Layout->setContentsMargins(0,0,0,0);
// add buttons
QToolButton *m_next_right_view_button =new QToolButton;
m_next_right_view_button->setDefaultAction(m_next_view_right);
m_next_right_view_button->setAutoRaise(true);
TopRightCorner_Layout->addWidget(m_next_right_view_button);
connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
connect(m_tab, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(tabDoubleClicked(int)));
connect(m_tab->tabBar(), SIGNAL(tabMoved(int, int)), this, SLOT(tabMoved(int, int)), Qt::QueuedConnection);
//arrows button to return on first view
QToolButton *m_first_view_button =new QToolButton;
m_first_view_button->setDefaultAction(m_first_view);
m_first_view_button->setAutoRaise(true);
m_tab->setCornerWidget(m_first_view_button, Qt::TopLeftCorner);
//arrows button to go on last view
QToolButton *m_end_view_button =new QToolButton;
m_end_view_button->setDefaultAction(m_end_view);
m_end_view_button->setAutoRaise(true);
TopRightCorner_Layout->addWidget(m_end_view_button);
QWidget *tabwidget=new QWidget(this);
tabwidget->setLayout(TopRightCorner_Layout);
m_tab -> setCornerWidget(tabwidget, Qt::TopRightCorner);
QToolButton *add_new_diagram_button = new QToolButton;
add_new_diagram_button -> setDefaultAction(m_add_new_diagram);
add_new_diagram_button -> setAutoRaise(true);
TopRightCorner_Layout->addWidget(add_new_diagram_button);
// some place right to the 'add_new_diagram_button' button
TopRightCorner_Layout->addSpacing(5);
QToolButton *m_first_view_button =new QToolButton;
m_first_view_button->setDefaultAction(m_first_view);
m_first_view_button->setAutoRaise(true);
TopLeftCorner_Layout->addWidget(m_first_view_button);
QToolButton *m_next_left_view_button =new QToolButton;
m_next_left_view_button->setDefaultAction(m_next_view_left);
m_next_left_view_button->setAutoRaise(true);
TopLeftCorner_Layout->addWidget(m_next_left_view_button);
// some place right to the 'first_view_button' button
TopLeftCorner_Layout->addSpacing(10);
// add widgets to tabbar
QWidget *tabwidgetRight=new QWidget(this);
tabwidgetRight->setLayout(TopRightCorner_Layout);
m_tab -> setCornerWidget(tabwidgetRight, Qt::TopRightCorner);
QWidget *tabwidgetLeft=new QWidget(this);
tabwidgetLeft->setLayout(TopLeftCorner_Layout);
m_tab -> setCornerWidget(tabwidgetLeft, Qt::TopLeftCorner);
// manage signals
connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
connect(m_tab, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(tabDoubleClicked(int)));
connect(m_tab->tabBar(), SIGNAL(tabMoved(int,int)), this, SLOT(tabMoved(int,int)), Qt::QueuedConnection);
fallback_widget_ -> setVisible(false);
m_tab -> setVisible(false);
+4 -2
View File
@@ -168,8 +168,10 @@ class ProjectView : public QWidget
// attributes
private:
QAction *m_add_new_diagram,
*m_first_view,
*m_end_view;
*m_first_view,
*m_end_view,
*m_next_view_left,
*m_next_view_right;
QETProject *m_project;
QVBoxLayout *layout_;
QWidget *fallback_widget_;
+16 -3
View File
@@ -76,6 +76,16 @@ QDomElement ElementData::kindInfoToXml(QDomDocument &document)
xml_type.appendChild(type_txt);
returned_elmt.appendChild(xml_type);
// Save max_slaves only if a specific limit is set (not default -1)
if (m_max_slaves != -1) {
auto xml_max_slaves = document.createElement(QStringLiteral("kindInformation"));
xml_max_slaves.setAttribute(QStringLiteral("name"), QStringLiteral("max_slaves"));
auto max_slaves_txt = document.createTextNode(QString::number(m_max_slaves));
xml_max_slaves.appendChild(max_slaves_txt);
returned_elmt.appendChild(xml_max_slaves);
}
}
else if (m_type == ElementData::Slave)
{
@@ -558,9 +568,12 @@ void ElementData::kindInfoFromXml(const QDomElement &xml_element)
}
auto name = dom_elmt.attribute(QStringLiteral("name"));
if (m_type == ElementData::Master &&
name == QLatin1String("type")) {
m_master_type = masterTypeFromString(dom_elmt.text());
if (m_type == ElementData::Master) {
if (name == QLatin1String("type")) {
m_master_type = masterTypeFromString(dom_elmt.text());
} else if (name == QLatin1String("max_slaves")) {
m_max_slaves = dom_elmt.text().toInt();
}
}
else if (m_type == ElementData::Slave ) {
if (name == QLatin1String("type")) {
+2 -1
View File
@@ -134,6 +134,7 @@ class ElementData : public PropertiesInterface
ElementData::Type m_type = ElementData::Simple;
ElementData::MasterType m_master_type = ElementData::Coil;
int m_max_slaves{-1};
ElementData::SlaveType m_slave_type = ElementData::SSimple;
ElementData::SlaveState m_slave_state = ElementData::NO;
@@ -141,7 +142,7 @@ class ElementData : public PropertiesInterface
ElementData::TerminalType m_terminal_type = ElementData::TTGeneric;
ElementData::TerminalFunction m_terminal_function = ElementData::TFGeneric;
int m_contact_count = 1;
int m_contact_count{1};
DiagramContext m_informations;
NamesList m_names_list;
QString m_drawing_information;
+47
View File
@@ -91,6 +91,8 @@ QString QETApp::m_user_company_tbt_dir = QString();
QString QETApp::m_user_custom_tbt_dir = QString();
QString QETApp::m_user_macros_dir = QString();
QETApp *QETApp::m_qetapp = nullptr;
bool lang_is_set = false;
@@ -724,6 +726,8 @@ void QETApp::resetCollectionsPath()
m_user_company_tbt_dir.clear();
m_user_custom_tbt_dir.clear();
m_user_macros_dir.clear();
}
/**
@@ -822,6 +826,38 @@ QString QETApp::customTitleBlockTemplatesDir()
return(dataDir() + "/titleblocks/");
}
/**
* @brief QETApp::userMacrosDir
* @return the path of the directory containing the user macros collection.
*/
QString QETApp::userMacrosDir()
{
if (m_user_macros_dir.isEmpty())
{
QSettings settings;
QString path = settings.value(
"elements-collections/macros-path",
"default").toString();
if (path != "default" && !path.isEmpty())
{
QDir dir(path);
if (dir.exists())
{
m_user_macros_dir = path;
return m_user_macros_dir;
}
}
else {
m_user_macros_dir = "default";
}
}
else if (m_user_macros_dir != "default") {
return m_user_macros_dir;
}
return(dataDir() + "/macros/");
}
/**
@brief QETApp::configDir
Return the QET configuration folder, i.e. the path to the folder in
@@ -938,6 +974,8 @@ QString QETApp::realPath(const QString &sym_path) {
directory = commonElementsDir();
} else if (sym_path.startsWith("company://")) {
directory = companyElementsDir();
} else if (sym_path.startsWith("macros://")) {
directory = userMacrosDir();
} else if (sym_path.startsWith("company://")) {
directory = companyElementsDir();
} else if (sym_path.startsWith("custom://")) {
@@ -976,6 +1014,7 @@ QString QETApp::symbolicPath(const QString &real_path) {
QString commond = commonElementsDir();
QString companyd = companyElementsDir();
QString customd = customElementsDir();
QString macrosd = userMacrosDir();
QString chemin;
// analyzes the file path passed in parameter
// analyse le chemin de fichier passe en parametre
@@ -987,6 +1026,10 @@ QString QETApp::symbolicPath(const QString &real_path) {
chemin = "company://"
+ real_path.right(
real_path.length() - companyd.length());
} else if (real_path.startsWith(macrosd)) {
chemin = "macros://"
+ real_path.right(
real_path.length() - macrosd.length());
} else if (real_path.startsWith(customd)) {
chemin = "custom://"
+ real_path.right(
@@ -2212,6 +2255,10 @@ void QETApp::initConfiguration()
if (!custom_tbt_dir.exists())
custom_tbt_dir.mkpath(QETApp::customTitleBlockTemplatesDir());
QDir macros_dir(QETApp::userMacrosDir());
if (!macros_dir.exists())
macros_dir.mkpath(QETApp::userMacrosDir());
/* recent files
* note:
* icons must be initialized before these instructions
+2 -1
View File
@@ -91,6 +91,7 @@ class QETApp : public QObject
static QString commonTitleBlockTemplatesDir();
static QString companyTitleBlockTemplatesDir();
static QString customTitleBlockTemplatesDir();
static QString userMacrosDir();
static bool registerProject(QETProject *);
static bool unregisterProject(QETProject *);
static QMap<uint, QETProject *> registeredProjects();
@@ -242,7 +243,7 @@ class QETApp : public QObject
static QString m_user_company_tbt_dir;
static QString m_user_custom_tbt_dir;
static QString m_user_macros_dir;
public slots:
void systray(QSystemTrayIcon::ActivationReason);
+74 -8
View File
@@ -45,6 +45,8 @@
#include "TerminalStrip/ui/terminalstripeditorwindow.h"
#include "ui/diagrameditorhandlersizewidget.h"
#include "TerminalStrip/ui/addterminalstripitemdialog.h"
#include "wiringlistexport.h"
#include "ui/terminalnumberingdialog.h"
#ifdef BUILD_WITHOUT_KF5
#else
@@ -465,13 +467,27 @@ void QETDiagramEditor::setUpActions()
wne.toCsv();
}
});
#ifdef QET_EXPORT_PROJECT_DB
m_export_project_db = new QAction(QET::Icons::DocumentSpreadsheet, tr("Exporter la base de donnée interne du projet"), this);
connect(m_export_project_db, &QAction::triggered, [this]() {
projectDataBase::exportDb(this->currentProject()->dataBase(), this);
// Export wiring list to CSV
m_project_export_wiring_list = new QAction(QET::Icons::DocumentSpreadsheet, tr("Exporter le plan de câblage"), this);
connect(m_project_export_wiring_list, &QAction::triggered, [this]() {
QETProject *project = this->currentProject();
if (project)
{
WiringListExport wle(project, this);
wle.toCsv();
}
});
#endif
// Terminal Numbering
m_terminal_numbering = new QAction(QET::Icons::TerminalStrip, tr("Numérotation automatique des bornes"), this);
connect(m_terminal_numbering, &QAction::triggered, this, &QETDiagramEditor::slot_terminalNumbering);
#ifdef QET_EXPORT_PROJECT_DB
m_export_project_db = new QAction(QET::Icons::DocumentSpreadsheet, tr("Exporter la base de donnée interne du projet"), this);
connect(m_export_project_db, &QAction::triggered, [this]() {
projectDataBase::exportDb(this->currentProject()->dataBase(), this);
});
#endif
//MDI view style
m_tabbed_view_mode = new QAction(tr("en utilisant des onglets"), this);
@@ -835,6 +851,8 @@ void QETDiagramEditor::setUpMenu()
menu_project -> addAction(m_project_export_conductor_num);
menu_project -> addAction(m_terminal_strip_dialog);
menu_project -> addAction(m_project_terminalBloc);
menu_project -> addAction(m_project_export_wiring_list);
menu_project -> addAction(m_terminal_numbering);
#ifdef QET_EXPORT_PROJECT_DB
menu_project -> addSeparator();
menu_project -> addAction(m_export_project_db);
@@ -1567,6 +1585,8 @@ void QETDiagramEditor::slot_updateActions()
m_csv_export -> setEnabled(editable_project);
m_project_export_conductor_num-> setEnabled(opened_project);
m_terminal_strip_dialog -> setEnabled(editable_project);
m_project_export_wiring_list -> setEnabled(opened_project);
m_terminal_numbering -> setEnabled(editable_project);
#ifdef QET_EXPORT_PROJECT_DB
m_export_project_db -> setEnabled(editable_project);
#endif
@@ -1828,6 +1848,31 @@ void QETDiagramEditor::addProjectView(ProjectView *project_view)
connect(project_view, SIGNAL(errorEncountered(QString)),
this, SLOT(showError(const QString &)));
//Highlight the current page
connect(project_view, &ProjectView::diagramActivated, this, [this](DiagramView *dv) {
if (dv && dv->diagram() && pa) {
// 1. Find the item in the tree that corresponds to this diagram
QTreeWidgetItem *item = pa->elementsPanel().getItemForDiagram(dv->diagram());
// 2. If you find it, select it
if (item) {
pa->elementsPanel().setCurrentItem(item);
}
}
});
//Highlight the current page in projectView on project activation
connect(this, &QETDiagramEditor::syncElementsPanel, this, [this]() {
if (pa && currentDiagramView()) {
// In the tree, find the element that corresponds to the diagram of the selected project.
QTreeWidgetItem *item = pa->elementsPanel().getItemForDiagram(currentDiagramView()->diagram());
if (item) {
// select the diagram
pa->elementsPanel().setCurrentItem(item);
}
}
});
//We maximise the new window if the current window is inexistent or maximized
QWidget *current_window = m_workspace.activeSubWindow();
bool maximise = ((!current_window)
@@ -2336,6 +2381,7 @@ void QETDiagramEditor::subWindowActivated(QMdiSubWindow *subWindows)
slot_updateActions();
slot_updateWindowsMenu();
emit syncElementsPanel();
}
/**
@@ -2471,7 +2517,27 @@ void QETDiagramEditor::generateTerminalBlock()
#endif
if ( !success ) {
QMessageBox::warning(nullptr,
QObject::tr("Error launching qet_tb_generator plugin"),
message);
QObject::tr("Error launching qet_tb_generator plugin"),
message);
}
}
/**
* @brief QETDiagramEditor::slot_terminalNumbering
* Opens the dialog for automatic terminal numbering and applies the generated undo command.
*/
void QETDiagramEditor::slot_terminalNumbering() {
TerminalNumberingDialog dialog(this);
if (dialog.exec() == QDialog::Accepted) {
QETProject *project = currentProject();
if (!project) return;
// Fetch the generated undo command from the dialog logic
QUndoCommand *macro = dialog.getUndoCommand(project);
// If changes were made, push them to the global undo stack
if (macro) {
undo_group.activeStack()->push(macro);
}
}
}
+7
View File
@@ -42,6 +42,7 @@ class RecentFiles;
class DiagramPropertiesEditorDockWidget;
class ElementsCollectionWidget;
class AutoNumberingDockWidget;
class TerminalNumberingDialog;
#ifdef BUILD_WITHOUT_KF5
#else
@@ -98,6 +99,9 @@ class QETDiagramEditor : public QETMainWindow
ProjectView *findProject(const QString &) const;
QMdiSubWindow *subWindowForWidget(QWidget *) const;
signals:
void syncElementsPanel();
public slots:
void save();
void saveAs();
@@ -129,6 +133,7 @@ class QETDiagramEditor : public QETMainWindow
void projectWasClosed(ProjectView *);
void editProjectProperties(ProjectView *);
void editProjectProperties(QETProject *);
void slot_terminalNumbering();
void editDiagramProperties(DiagramView *);
void editDiagramProperties(Diagram *);
void addDiagramToProject(QETProject *);
@@ -197,6 +202,8 @@ class QETDiagramEditor : public QETMainWindow
*m_terminal_strip_dialog = nullptr, ///<Launch terminal strip dialog
*m_project_terminalBloc, ///< generate terminal block
*m_project_export_conductor_num,///<Export the wire num to csv
*m_project_export_wiring_list, ///< Action to export the wiring list
*m_terminal_numbering, ///< Action to launch terminal numbering
*m_export_project_db, ///Export to file the internal database of the current project
*m_tile_window, ///< Show MDI subwindows as tile
*m_cascade_window, ///< Show MDI subwindows as cascade
@@ -1351,6 +1351,7 @@ void DynamicElementTextItem::updateXref()
{
m_slave_Xref_item = new QGraphicsTextItem(xref_label, this);
m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5));
m_slave_Xref_item->setDefaultTextColor(Qt::black);
m_slave_Xref_item->installSceneEventFilter(this);
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::xChanged, this, &DynamicElementTextItem::updateXref);
+24
View File
@@ -183,3 +183,27 @@ void MasterElement::aboutDeleteXref()
return;
}
}
/**
* @brief MasterElement::isFull
* @return true if the master has reached its maximum number of slaves
*/
bool MasterElement::isFull() const
{
// Set default value to -1 (unlimited slaves)
int max_slaves = -1;
QVariant max_slaves_variant = kindInformations().value("max_slaves");
// Overwrite default if a valid limit is defined in the element's XML
if (max_slaves_variant.isValid() && !max_slaves_variant.toString().isEmpty()) {
max_slaves = max_slaves_variant.toInt();
}
// If no limit is set (-1), the master is never full
if (max_slaves == -1) {
return false;
}
// Return true if current connected elements reached or exceeded the limit
return connected_elements.size() >= max_slaves;
}
+2
View File
@@ -44,6 +44,8 @@ class MasterElement : public Element
void unlinkElement (Element *elmt) override;
void initLink (QETProject *project) override;
QRectF XrefBoundingRect() const;
bool isFull() const; // Check Slave-Limit
protected:
QVariant itemChange(
@@ -177,6 +177,15 @@ GeneralConfigurationPage::GeneralConfigurationPage(QWidget *parent) :
ui->m_custom_tbt_path_cb->blockSignals(false);
}
path = settings.value("elements-collections/macros-path", "default").toString();
if (path != "default")
{
ui->m_user_macros_path_cb->blockSignals(true);
ui->m_user_macros_path_cb->setCurrentIndex(1);
ui->m_user_macros_path_cb->setItemData(1, path, Qt::DisplayRole);
ui->m_user_macros_path_cb->blockSignals(false);
}
fillLang();
}
@@ -321,6 +330,21 @@ void GeneralConfigurationPage::applyConf()
if (path != settings.value("elements-collections/custom-tbt-path").toString()) {
QETApp::resetCollectionsPath();
}
path = settings.value("elements-collections/macros-path").toString();
if (ui->m_user_macros_path_cb->currentIndex() == 1)
{
QString path = ui->m_user_macros_path_cb->currentText();
QDir dir(path);
settings.setValue("elements-collections/macros-path",
dir.exists() ? path : "default");
}
else {
settings.setValue("elements-collections/macros-path", "default");
}
if (path != settings.value("elements-collections/macros-path").toString()) {
QETApp::resetCollectionsPath();
}
}
/**
@@ -512,6 +536,19 @@ void GeneralConfigurationPage::on_m_custom_tbt_path_cb_currentIndexChanged(int i
}
}
void GeneralConfigurationPage::on_m_user_macros_path_cb_currentIndexChanged(int index)
{
if (index == 1)
{
QString path = QFileDialog::getExistingDirectory(this, tr("Chemin des macros utilisateur"), QETApp::documentDir());
if (!path.isEmpty()) {
ui->m_user_macros_path_cb->setItemData(1, path, Qt::DisplayRole);
}
else {
ui->m_user_macros_path_cb->setCurrentIndex(0);
}
}
}
void GeneralConfigurationPage::on_m_indi_text_font_pb_clicked()
{
@@ -46,6 +46,7 @@ class GeneralConfigurationPage : public ConfigPage
void on_m_custom_elmt_path_cb_currentIndexChanged(int index);
void on_m_company_tbt_path_cb_currentIndexChanged(int index);
void on_m_custom_tbt_path_cb_currentIndexChanged(int index);
void on_m_user_macros_path_cb_currentIndexChanged(int index);
void on_m_indi_text_font_pb_clicked();
void on_MaxPartsElementEditorList_sb_valueChanged(int value);
void on_DiagramEditor_Grid_PointSize_min_sb_valueChanged(int value);
@@ -17,7 +17,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
@@ -349,6 +349,27 @@
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Répertoire des Macros utilisateur</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QComboBox" name="m_user_macros_path_cb">
<item>
<property name="text">
<string>Par defaut</string>
</property>
</item>
<item>
<property name="text">
<string>Parcourir...</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
+17
View File
@@ -160,6 +160,7 @@ void ElementInfoWidget::enableLiveEdit()
{
for (ElementInfoPartWidget *eipw : m_eipw_list)
connect(eipw, &ElementInfoPartWidget::textChanged, this, &ElementInfoWidget::apply);
connect(ui->m_auto_num_locked_cb, &QCheckBox::clicked, this, &ElementInfoWidget::apply);
}
/**
@@ -170,6 +171,7 @@ void ElementInfoWidget::disableLiveEdit()
{
for (ElementInfoPartWidget *eipw : m_eipw_list)
disconnect(eipw, &ElementInfoPartWidget::textChanged, this, &ElementInfoWidget::apply);
disconnect(ui->m_auto_num_locked_cb, &QCheckBox::clicked, this, &ElementInfoWidget::apply);
}
/**
@@ -193,6 +195,12 @@ void ElementInfoWidget::buildInterface()
}
ui->scroll_vlayout->addStretch();
// Show checkbox only if the element is a terminal
if (m_element.data()->elementData().m_type == ElementData::Terminal) {
ui->m_auto_num_locked_cb->setVisible(true);
} else {
ui->m_auto_num_locked_cb->setVisible(false);
}
}
/**
@@ -231,6 +239,11 @@ void ElementInfoWidget::updateUi()
for (ElementInfoPartWidget *eipw : m_eipw_list) {
eipw -> setText (element_info[eipw->key()].toString());
}
// Load the lock status for auto numbering
if (m_element->elementData().m_type == ElementData::Terminal) {
QString lock_value = element_info.value(QStringLiteral("auto_num_locked")).toString();
ui->m_auto_num_locked_cb->setChecked(lock_value == QLatin1String("true"));
}
if (m_live_edit) {
enableLiveEdit();
@@ -259,6 +272,10 @@ DiagramContext ElementInfoWidget::currentInfo() const
}
}
// Save the auto numbering lock status
if (m_element->elementData().m_type == ElementData::Terminal) {
info_.addValue(QStringLiteral("auto_num_locked"), ui->m_auto_num_locked_cb->isChecked() ? QStringLiteral("true") : QStringLiteral("false"));
}
return info_;
}
+13
View File
@@ -29,6 +29,19 @@
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="m_auto_num_locked_cb">
<property name="text">
<string>Exclure de la numérotation auto</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="styleSheet">
<string notr="true">margin: 5px; font-weight: bold;</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy">
+4
View File
@@ -372,6 +372,10 @@ QWidget *ElementPropertiesWidget::generalWidget()
description_string += QString(tr("Rotation : %1°\n")).arg(m_element.data()->rotation());
description_string += QString(tr("Dimensions : %1*%2\n")).arg(m_element -> size().width()).arg(m_element -> size().height());
description_string += QString(tr("Bornes : %1\n")).arg(m_element -> terminals().count());
if (m_element->linkType() == Element::Master){
description_string += QString(tr("Nombre maximum de contacts esclaves définis : %1\n")).arg(m_element -> elementData().m_max_slaves);
description_string += QString(tr("Nombre de contacts esclaves utilisés : %1\n")).arg(m_element ->linkedElements().count());
}
description_string += QString(tr("Emplacement : %1\n")).arg(m_element.data()->location().toString());
// widget himself
+17 -2
View File
@@ -16,7 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linksingleelementwidget.h"
#include "../qetgraphicsitem/masterelement.h"
#include "../qetgraphicsitem/conductor.h"
#include "../diagram.h"
#include "../diagramposition.h"
@@ -386,7 +386,22 @@ QVector <QPointer<Element>> LinkSingleElementWidget::availableElements()
//If element is linked, remove is parent from the list
if(!m_element->isFree()) elmt_vector.removeAll(m_element->linkedElements().first());
// Filter out all master elements from the list
for (int i = elmt_vector.size() - 1; i >= 0; --i) {
Element *elmt = elmt_vector.at(i);
// If the item in the list is a master
if (elmt->linkType() == Element::Master) {
// We convert the generic element pointer into a MasterElement pointer
MasterElement *master = static_cast<MasterElement*>(elmt);
// If the master is full, we'll remove it from the list!
if (master->isFull()) {
elmt_vector.removeAt(i);
}
}
}
return elmt_vector;
}
+18 -1
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>389</width>
<height>442</height>
<height>460</height>
</rect>
</property>
<property name="windowTitle">
@@ -64,6 +64,23 @@
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QLabel" name="m_hidden_masters_label">
<property name="text">
<string>Remarque : les éléments maîtres ayant atteint leur nombre maximal d'esclaves sont masqués.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
+181 -159
View File
@@ -1,20 +1,20 @@
/*
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/>.
*/
* 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 "masterpropertieswidget.h"
#include "../diagram.h"
@@ -25,64 +25,65 @@
#include "ui_masterpropertieswidget.h"
#include <QListWidgetItem>
#include <QMessageBox>
/**
@brief MasterPropertiesWidget::MasterPropertiesWidget
Default constructor
@param elmt
@param parent
*/
* @brief MasterPropertiesWidget::MasterPropertiesWidget
* Default constructor
* @param elmt
* @param parent
*/
MasterPropertiesWidget::MasterPropertiesWidget(Element *elmt, QWidget *parent) :
AbstractElementPropertiesEditorWidget(parent),
ui(new Ui::MasterPropertiesWidget),
m_project(nullptr)
AbstractElementPropertiesEditorWidget(parent),
ui(new Ui::MasterPropertiesWidget),
m_project(nullptr)
{
ui->setupUi(this);
ui->m_free_tree_widget->setContextMenuPolicy(Qt::CustomContextMenu);
ui->m_link_tree_widget->setContextMenuPolicy(Qt::CustomContextMenu);
QStringList list;
QSettings settings;
if (settings.value("genericpanel/folio", false).toBool()) {
list << tr("Vignette")
<< tr("Label de folio")
<< tr("Titre de folio")
<< tr("Position");
<< tr("Label de folio")
<< tr("Titre de folio")
<< tr("Position");
}
else {
list << tr("Vignette")
<< tr("N° de folio")
<< tr("Titre de folio")
<< tr("Position");
<< tr("N° de folio")
<< tr("Titre de folio")
<< tr("Position");
}
ui->m_free_tree_widget->setHeaderLabels(list);
ui->m_link_tree_widget->setHeaderLabels(list);
m_context_menu = new QMenu(this);
m_link_action = new QAction(tr("Lier l'élément"), this);
m_unlink_action = new QAction(tr("Délier l'élément"), this);
m_show_qtwi = new QAction(tr("Montrer l'élément"), this);
m_show_element = new QAction(tr("Montrer l'élément maître"), this);
m_save_header_state = new QAction(tr("Enregistrer la disposition"), this);
connect(ui->m_free_tree_widget, &QTreeWidget::itemDoubleClicked,
this, &MasterPropertiesWidget::showElementFromTWI);
this, &MasterPropertiesWidget::showElementFromTWI);
connect(ui->m_link_tree_widget, &QTreeWidget::itemDoubleClicked,
this, &MasterPropertiesWidget::showElementFromTWI);
this, &MasterPropertiesWidget::showElementFromTWI);
connect(ui->m_free_tree_widget, &QTreeWidget::customContextMenuRequested,
[this](QPoint point) {this->customContextMenu(point, 1);});
[this](QPoint point) {this->customContextMenu(point, 1);});
connect(ui->m_link_tree_widget, &QTreeWidget::customContextMenuRequested,
[this](QPoint point) {this->customContextMenu(point, 2);});
[this](QPoint point) {this->customContextMenu(point, 2);});
connect(m_link_action, &QAction::triggered,
this, &MasterPropertiesWidget::on_link_button_clicked);
this, &MasterPropertiesWidget::on_link_button_clicked);
connect(m_unlink_action, &QAction::triggered,
this, &MasterPropertiesWidget::on_unlink_button_clicked);
this, &MasterPropertiesWidget::on_unlink_button_clicked);
connect(m_show_qtwi, &QAction::triggered,
[this]() {this->showElementFromTWI(this->m_qtwi_at_context_menu,0);});
[this]() {this->showElementFromTWI(this->m_qtwi_at_context_menu,0);});
connect(m_show_element, &QAction::triggered, [this]()
{
this->m_element->diagram()->showMe();
@@ -90,46 +91,46 @@ MasterPropertiesWidget::MasterPropertiesWidget(Element *elmt, QWidget *parent) :
if(this->m_showed_element)
m_showed_element->setHighlighted(false);
});
QHeaderView *qhv = ui->m_free_tree_widget->header();
qhv->setContextMenuPolicy(Qt::CustomContextMenu);
connect(qhv, &QHeaderView::customContextMenuRequested,
this, &MasterPropertiesWidget::headerCustomContextMenuRequested);
this, &MasterPropertiesWidget::headerCustomContextMenuRequested);
connect(m_save_header_state, &QAction::triggered, [qhv]()
{
QByteArray qba = qhv->saveState();
QSettings settings;
settings.setValue("link-element-widget/master-state", qba);
});
setElement(elmt);
}
/**
@brief MasterPropertiesWidget::~MasterPropertiesWidget
Destructor
*/
* @brief MasterPropertiesWidget::~MasterPropertiesWidget
* Destructor
*/
MasterPropertiesWidget::~MasterPropertiesWidget()
{
if (m_showed_element)
m_showed_element->setHighlighted(false);
if(m_element)
m_element->setHighlighted(false);
delete ui;
}
/**
@brief MasterPropertiesWidget::setElement
Set the element to be edited
@param element
*/
* @brief MasterPropertiesWidget::setElement
* Set the element to be edited
* @param element
*/
void MasterPropertiesWidget::setElement(Element *element)
{
if (m_element == element)
return;
if (m_showed_element)
{
m_showed_element->setHighlighted(false);
@@ -137,40 +138,40 @@ void MasterPropertiesWidget::setElement(Element *element)
}
if (m_element)
m_element->setHighlighted(false);
if (m_project)
disconnect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)),
this, SLOT(diagramWasdeletedFromProject()));
this, SLOT(diagramWasdeletedFromProject()));
if(Q_LIKELY(element->diagram() && element->diagram()->project()))
{
m_project = element->diagram()->project();
connect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)),
this, SLOT(diagramWasdeletedFromProject()));
}
else
m_project = nullptr;
if(Q_LIKELY(element->diagram() && element->diagram()->project()))
{
m_project = element->diagram()->project();
connect(m_project, SIGNAL(diagramRemoved(QETProject*,Diagram*)),
this, SLOT(diagramWasdeletedFromProject()));
}
else
m_project = nullptr;
//Keep up to date this widget when the linked elements of m_element change
if (m_element)
disconnect(m_element.data(), &Element::linkedElementChanged,
this, &MasterPropertiesWidget::updateUi);
m_element = element;
this, &MasterPropertiesWidget::updateUi);
m_element = element;
connect(m_element.data(), &Element::linkedElementChanged,
this, &MasterPropertiesWidget::updateUi);
this, &MasterPropertiesWidget::updateUi);
updateUi();
}
/**
@brief MasterPropertiesWidget::apply
If link between edited element and other change,
apply the change with a QUndoCommand (got with method associatedUndo)
pushed to the stack of element project.
Return true if link change, else false
@note is void no Return ???
*/
* @brief MasterPropertiesWidget::apply
* If link between edited element and other change,
* apply the change with a QUndoCommand (got with method associatedUndo)
* pushed to the stack of element project.
* Return true if link change, else false
* @note is void no Return ???
*/
void MasterPropertiesWidget::apply()
{
if (QUndoCommand *undo = associatedUndo())
@@ -178,25 +179,25 @@ void MasterPropertiesWidget::apply()
}
/**
@brief MasterPropertiesWidget::reset
Reset current widget, clear eveything and rebuild widget.
*/
* @brief MasterPropertiesWidget::reset
* Reset current widget, clear eveything and rebuild widget.
*/
void MasterPropertiesWidget::reset()
{
foreach (QTreeWidgetItem *qtwi, m_qtwi_hash.keys())
delete qtwi;
m_qtwi_hash.clear();
updateUi();
}
/**
@brief MasterPropertiesWidget::associatedUndo
If link between the edited element and other change,
return a QUndoCommand with this change.
If no change return nullptr.
@return
*/
* @brief MasterPropertiesWidget::associatedUndo
* If link between the edited element and other change,
* return a QUndoCommand with this change.
* If no change return nullptr.
* @return
*/
QUndoCommand* MasterPropertiesWidget::associatedUndo() const
{
QList <Element *> to_link;
@@ -205,7 +206,7 @@ QUndoCommand* MasterPropertiesWidget::associatedUndo() const
for (int i=0; i<ui->m_link_tree_widget->topLevelItemCount(); i++)
to_link << m_qtwi_hash[ui->m_link_tree_widget->topLevelItem(i)];
//The two list contain the same element, there is no change
//The two list contain the same element, there is no change
if (to_link.size() == linked_.size())
{
bool equal = true;
@@ -229,11 +230,11 @@ QUndoCommand* MasterPropertiesWidget::associatedUndo() const
}
/**
@brief MasterPropertiesWidget::setLiveEdit
@param live_edit = true : live edit is enable
else false : live edit is disable.
@return always true because live edit is handled by this editor widget
*/
* @brief MasterPropertiesWidget::setLiveEdit
* @param live_edit = true : live edit is enable
* else false : live edit is disable.
* @return always true because live edit is handled by this editor widget
*/
bool MasterPropertiesWidget::setLiveEdit(bool live_edit)
{
m_live_edit = live_edit;
@@ -241,9 +242,9 @@ bool MasterPropertiesWidget::setLiveEdit(bool live_edit)
}
/**
@brief MasterPropertiesWidget::updateUi
Build the interface of the widget
*/
* @brief MasterPropertiesWidget::updateUi
* Build the interface of the widget
*/
void MasterPropertiesWidget::updateUi()
{
ui->m_free_tree_widget->clear();
@@ -256,75 +257,75 @@ void MasterPropertiesWidget::updateUi()
ElementProvider elmt_prov(m_project);
QSettings settings;
//Build the list of free available element
//Build the list of free available element
QList <QTreeWidgetItem *> items_list;
for(const auto &elmt : elmt_prov.freeElement(ElementData::Slave))
{
QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_free_tree_widget);
qtwi->setIcon(0, elmt->pixmap());
if(settings.value("genericpanel/folio", false).toBool())
{
autonum::sequentialNumbers seq;
QString F =autonum::AssignVariables::formulaToLabel(
elmt->diagram()->border_and_titleblock.folio(),
seq,
elmt->diagram(),
elmt);
elmt->diagram()->border_and_titleblock.folio(),
seq,
elmt->diagram(),
elmt);
qtwi->setText(1, F);
}
else
{
qtwi->setText(1, QString::number(
elmt->diagram()->folioIndex()
+ 1));
elmt->diagram()->folioIndex()
+ 1));
}
qtwi->setText(2, elmt->diagram()->title());
qtwi->setText(4, elmt->diagram()->convertPosition(
elmt->scenePos()).toString());
elmt->scenePos()).toString());
items_list.append(qtwi);
m_qtwi_hash.insert(qtwi, elmt);
}
ui->m_free_tree_widget->addTopLevelItems(items_list);
items_list.clear();
//Build the list of already linked element
//Build the list of already linked element
const QList<Element *> link_list = m_element->linkedElements();
for(Element *elmt : link_list)
{
QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_link_tree_widget);
qtwi->setIcon(0, elmt->pixmap());
if(settings.value("genericpanel/folio", false).toBool())
{
autonum::sequentialNumbers seq;
QString F =autonum::AssignVariables::formulaToLabel(
elmt->diagram()->border_and_titleblock.folio(),
seq,
elmt->diagram(),
elmt);
elmt->diagram()->border_and_titleblock.folio(),
seq,
elmt->diagram(),
elmt);
qtwi->setText(1, F);
}
else
{
qtwi->setText(1, QString::number(
elmt->diagram()->folioIndex()
+ 1));
elmt->diagram()->folioIndex()
+ 1));
}
qtwi->setText(2, elmt->diagram()->title());
qtwi->setText(3, elmt->diagram()->convertPosition(
elmt->scenePos()).toString());
elmt->scenePos()).toString());
items_list.append(qtwi);
m_qtwi_hash.insert(qtwi, elmt);
}
if(items_list.count())
ui->m_link_tree_widget->addTopLevelItems(items_list);
QVariant v = settings.value("link-element-widget/master-state");
if(!v.isNull())
{
@@ -334,9 +335,9 @@ void MasterPropertiesWidget::updateUi()
}
/**
@brief MasterPropertiesWidget::headerCustomContextMenuRequested
@param pos
*/
* @brief MasterPropertiesWidget::headerCustomContextMenuRequested
* @param pos
*/
void MasterPropertiesWidget::headerCustomContextMenuRequested(const QPoint &pos)
{
m_context_menu->clear();
@@ -345,36 +346,57 @@ void MasterPropertiesWidget::headerCustomContextMenuRequested(const QPoint &pos)
}
/**
@brief MasterPropertiesWidget::on_link_button_clicked
move current item in the free_list to linked_list
*/
* @brief MasterPropertiesWidget::on_link_button_clicked
* Moves the current item from the free_list to the linked_list,
* provided the master's slave limit has not been reached.
*/
void MasterPropertiesWidget::on_link_button_clicked()
{
//take the current item from free_list and push it to linked_list
// Get the maximum number of allowed slaves from the element's information
QVariant max_slaves_variant = m_element->kindInformations().value("max_slaves");
if (max_slaves_variant.isValid() && !max_slaves_variant.toString().isEmpty()) {
int max_slaves = max_slaves_variant.toInt();
int current_slaves = ui->m_link_tree_widget->topLevelItemCount();
// If a limit is set and reached
if (max_slaves != -1 && current_slaves >= max_slaves) {
// Show a message box with the actual window as parent to ensure it's on top
QMessageBox::warning(this->window(),
tr("Nombre maximal d'esclaves atteint."),
tr("Cet élément maître ne peut plus accepter aucun nouveau contact esclave, la limite fixée a été atteinte (Limite: %1).").arg(max_slaves));
return;
}
}
// Move current item from free_list to linked_list
QTreeWidgetItem *qtwi = ui->m_free_tree_widget->currentItem();
if (qtwi)
{
ui->m_free_tree_widget->takeTopLevelItem(
ui->m_free_tree_widget->indexOfTopLevelItem(qtwi));
ui->m_free_tree_widget->indexOfTopLevelItem(qtwi));
ui->m_link_tree_widget->insertTopLevelItem(0, qtwi);
if(m_live_edit)
apply();
}
}
/**
@brief MasterPropertiesWidget::on_unlink_button_clicked
move current item in linked_list to free_list
*/
* @brief MasterPropertiesWidget::on_unlink_button_clicked
* move current item in linked_list to free_list
*/
void MasterPropertiesWidget::on_unlink_button_clicked()
{
//take the current item from linked_list and push it to free_list
//take the current item from linked_list and push it to free_list
QTreeWidgetItem *qtwi = ui->m_link_tree_widget->currentItem();
if(qtwi)
{
ui->m_link_tree_widget->takeTopLevelItem(
ui->m_link_tree_widget->indexOfTopLevelItem(qtwi));
ui->m_link_tree_widget->indexOfTopLevelItem(qtwi));
ui->m_free_tree_widget->insertTopLevelItem(0, qtwi);
if(m_live_edit)
@@ -383,18 +405,18 @@ void MasterPropertiesWidget::on_unlink_button_clicked()
}
/**
@brief MasterPropertiesWidget::showElementFromTWI
Show the element corresponding to the given QTreeWidgetItem
@param qtwi
@param column
*/
* @brief MasterPropertiesWidget::showElementFromTWI
* Show the element corresponding to the given QTreeWidgetItem
* @param qtwi
* @param column
*/
void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int column)
{
Q_UNUSED(column);
if (m_showed_element)
{
disconnect(m_showed_element, SIGNAL(destroyed()),
this, SLOT(showedElementWasDeleted()));
this, SLOT(showedElementWasDeleted()));
m_showed_element -> setHighlighted(false);
}
if (m_element)
@@ -404,23 +426,23 @@ void MasterPropertiesWidget::showElementFromTWI(QTreeWidgetItem *qtwi, int colum
m_showed_element->diagram()->showMe();
m_showed_element->setHighlighted(true);
connect(m_showed_element, SIGNAL(destroyed()),
this, SLOT(showedElementWasDeleted()));
this, SLOT(showedElementWasDeleted()));
}
/**
@brief MasterPropertiesWidget::showedElementWasDeleted
Set to nullptr the current showed element when he was deleted
*/
* @brief MasterPropertiesWidget::showedElementWasDeleted
* Set to nullptr the current showed element when he was deleted
*/
void MasterPropertiesWidget::showedElementWasDeleted()
{
m_showed_element = nullptr;
}
/**
@brief MasterPropertiesWidget::diagramWasdeletedFromProject
This slot is called when a diagram is removed from the parent project
of edited element to update the content of this widget
*/
* @brief MasterPropertiesWidget::diagramWasdeletedFromProject
* This slot is called when a diagram is removed from the parent project
* of edited element to update the content of this widget
*/
void MasterPropertiesWidget::diagramWasdeletedFromProject()
{
// We use a timer because if the removed diagram
@@ -431,11 +453,11 @@ void MasterPropertiesWidget::diagramWasdeletedFromProject()
}
/**
@brief MasterPropertiesWidget::customContextMenu
Display a context menu
@param pos
@param i : the tree widget where the context menu was requested.
*/
* @brief MasterPropertiesWidget::customContextMenu
* Display a context menu
* @param pos
* @param i : the tree widget where the context menu was requested.
*/
void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
{
// add the size of the header to display the topleft of the QMenu
@@ -444,14 +466,14 @@ void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
// section related to QAbstractScrollArea
QPoint point = pos;
point.ry()+=ui->m_free_tree_widget->header()->height();
m_context_menu->clear();
if (i == 1)
{
point = ui->m_free_tree_widget->mapToGlobal(point);
//Context at for free tree widget
//Context at for free tree widget
if (ui->m_free_tree_widget->currentItem())
{
m_qtwi_at_context_menu = ui->m_free_tree_widget->currentItem();
@@ -462,8 +484,8 @@ void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
else
{
point = ui->m_link_tree_widget->mapToGlobal(point);
//context at for link tre widget
//context at for link tre widget
if (ui->m_link_tree_widget->currentItem())
{
m_qtwi_at_context_menu = ui->m_link_tree_widget->currentItem();
@@ -471,7 +493,7 @@ void MasterPropertiesWidget::customContextMenu(const QPoint &pos, int i)
m_context_menu->addAction(m_show_qtwi);
}
}
m_context_menu->addAction(m_show_element);
m_context_menu->popup(point);
}
+178
View File
@@ -0,0 +1,178 @@
#include "terminalnumberingdialog.h"
#include "ui_terminalnumberingdialog.h"
#include "../qetproject.h"
#include "../diagram.h"
#include "../qetgraphicsitem/element.h"
#include "../undocommand/changeelementinformationcommand.h"
#include <QUndoCommand>
#include <algorithm>
/**
* @brief TerminalNumberingDialog::TerminalNumberingDialog
* Constructor
* @param parent
*/
TerminalNumberingDialog::TerminalNumberingDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::TerminalNumberingDialog)
{
ui->setupUi(this);
}
/**
* @brief TerminalNumberingDialog::~TerminalNumberingDialog
* Destructor
*/
TerminalNumberingDialog::~TerminalNumberingDialog()
{
delete ui;
}
/**
* @brief TerminalNumberingDialog::isXAxisPriority
* @return true if X axis has priority, false if Y axis has priority
*/
bool TerminalNumberingDialog::isXAxisPriority() const
{
return ui->rb_priority_x->isChecked();
}
/**
* @brief TerminalNumberingDialog::isAlphanumeric
* @return true if alphanumeric sorting is enabled, false if numeric only
*/
bool TerminalNumberingDialog::isAlphanumeric() const
{
return ui->rb_type_alpha->isChecked();
}
/**
* @brief TerminalNumberingDialog::getUndoCommand
* Scans the given project for terminals, sorts them according to user preferences
* (X/Y axis, alphanumeric rules), and generates an undo command containing all label changes.
* * @param project Pointer to the current QETProject
* @return QUndoCommand* containing the modifications, or nullptr if no changes are needed.
*/
QUndoCommand* TerminalNumberingDialog::getUndoCommand(QETProject *project) const {
if (!project) return nullptr;
bool axisX = isXAxisPriority();
bool alpha = isAlphanumeric();
// 1. Helper structure to store and sort terminal data
struct TermInfo {
Element *elmt;
QString prefix;
QString suffix;
int folioIndex;
qreal x;
qreal y;
};
QList<TermInfo> termList;
// 2. Collect all terminals from all folios in the project
foreach (Diagram *diagram, project->diagrams()) {
int fIndex = diagram->folioIndex();
foreach (QGraphicsItem *qgi, diagram->items()) {
if (Element *elmt = qgraphicsitem_cast<Element *>(qgi)) {
// Check if the element is actually a terminal
if (elmt->elementData().m_type == ElementData::Terminal) {
DiagramContext info = elmt->elementInformations();
// Ignore locked terminals (if the user checked a 'lock' property)
if (info.value(QStringLiteral("auto_num_locked")).toString() == QLatin1String("true")) {
continue;
}
QString label = elmt->actualLabel();
if (label.isEmpty()) continue;
// Split prefix (e.g., "-X1") and suffix (e.g., "1" or "A")
QString prefix = label;
QString suffix = "";
int colonIndex = label.lastIndexOf(':');
if (colonIndex != -1) {
prefix = label.left(colonIndex);
suffix = label.mid(colonIndex + 1);
}
// If user chose purely numeric, skip terminals with alphabetical suffixes
if (!alpha && !suffix.isEmpty()) {
bool isNum;
suffix.toInt(&isNum);
if (!isNum) continue;
}
TermInfo ti;
ti.elmt = elmt;
ti.prefix = prefix;
ti.suffix = suffix;
ti.folioIndex = fIndex;
ti.x = elmt->pos().x();
ti.y = elmt->pos().y();
termList.append(ti);
}
}
}
}
// 3. Sort terminals based on user selection (X or Y axis priority)
std::sort(termList.begin(), termList.end(), [axisX](const TermInfo &a, const TermInfo &b) {
// First sort by BMK Prefix alphabetically (case insensitive)
int prefixCmp = a.prefix.compare(b.prefix, Qt::CaseInsensitive);
if (prefixCmp != 0) return prefixCmp < 0;
// Then sort by folio (page) index
if (a.folioIndex != b.folioIndex) return a.folioIndex < b.folioIndex;
// Finally sort by coordinates (with a 1.0px tolerance to handle slight misalignments)
if (axisX) {
if (qAbs(a.x - b.x) > 1.0) return a.x < b.x;
return a.y < b.y;
} else {
if (qAbs(a.y - b.y) > 1.0) return a.y < b.y;
return a.x < b.x;
}
});
// 4. Generate new numbering and create the undo command macro
QUndoCommand *macro = new QUndoCommand(QObject::tr("Automatic terminal numbering"));
QMap<QString, int> counters;
foreach (const TermInfo &ti, termList) {
// Increment the counter for this terminal block (e.g., "-X3")
counters[ti.prefix]++;
int newNum = counters[ti.prefix];
// Determine if the original suffix was a pure number
QString newLabel;
bool isNum;
ti.suffix.toInt(&isNum);
if (isNum || ti.suffix.isEmpty()) {
// If it was a number (e.g., "1") or empty, update it with the new counter
newLabel = ti.prefix + ":" + QString::number(newNum);
} else {
// If it was alphabetical (e.g., "N", "PE"), keep the original text but consume the count!
newLabel = ti.prefix + ":" + ti.suffix;
}
DiagramContext oldInfo = ti.elmt->elementInformations();
DiagramContext newInfo = oldInfo;
newInfo.addValue(QStringLiteral("label"), newLabel);
// Create an undo command only if the label actually changes
if (oldInfo != newInfo) {
new ChangeElementInformationCommand(ti.elmt, oldInfo, newInfo, macro);
}
}
// 5. Return the macro if it contains changes, otherwise delete and return null
if (macro->childCount() > 0) {
return macro;
} else {
delete macro;
return nullptr;
}
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef TERMINALNUMBERINGDIALOG_H
#define TERMINALNUMBERINGDIALOG_H
#include <QDialog>
class QETProject;
class QUndoCommand;
namespace Ui {
class TerminalNumberingDialog;
}
/**
* @brief The TerminalNumberingDialog class
* Dialog to configure the automatic numbering of terminals.
*/
class TerminalNumberingDialog : public QDialog
{
Q_OBJECT
public:
explicit TerminalNumberingDialog(QWidget *parent = nullptr);
~TerminalNumberingDialog();
// Getters for the user's choices
bool isXAxisPriority() const;
bool isAlphanumeric() const;
QUndoCommand* getUndoCommand(QETProject *project) const;
private:
Ui::TerminalNumberingDialog *ui;
};
#endif // TERMINALNUMBERINGDIALOG_H

Some files were not shown because too many files have changed in this diff Show More