mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-06-19 12:44:13 +02:00
Merge branch 'master' into master
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "org.qelectrotech.QElectroTech",
|
"id": "org.qelectrotech.QElectroTech",
|
||||||
"base-version": "5.15-23.08",
|
|
||||||
"runtime": "org.kde.Platform",
|
"runtime": "org.kde.Platform",
|
||||||
"runtime-version": "5.15-23.08",
|
"runtime-version": "5.15-25.08",
|
||||||
"sdk": "org.kde.Sdk",
|
"sdk": "org.kde.Sdk",
|
||||||
"command": "qelectrotech",
|
"command": "qelectrotech",
|
||||||
"rename-desktop-file": "org.qelectrotech.qelectrotech.desktop",
|
"rename-desktop-file": "org.qelectrotech.qelectrotech.desktop",
|
||||||
@@ -18,51 +17,17 @@
|
|||||||
"--socket=cups",
|
"--socket=cups",
|
||||||
"--filesystem=host"
|
"--filesystem=host"
|
||||||
],
|
],
|
||||||
"modules": [
|
"cleanup": [
|
||||||
{
|
"/include",
|
||||||
"name": "tkinter",
|
"/man",
|
||||||
"buildsystem": "simple",
|
"/share/doc",
|
||||||
"build-commands": [
|
"/share/man",
|
||||||
"pip3 install --prefix=${FLATPAK_DEST} ."
|
"*.la",
|
||||||
],
|
"*.a"
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/iwalton3/tkinter-standalone",
|
|
||||||
"commit": "23c793bad2429f4a81eee9f50e2d07ae845b7785"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"modules": [
|
"modules": [
|
||||||
{
|
"tkinter.json",
|
||||||
"name": "tcl",
|
"pypi-dependencies.json",
|
||||||
"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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "qelectrotech",
|
"name": "qelectrotech",
|
||||||
"buildsystem": "qmake",
|
"buildsystem": "qmake",
|
||||||
@@ -76,37 +41,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "patch",
|
"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
|
||||||
|
|
||||||
+3
-16
@@ -1,16 +1,6 @@
|
|||||||
From 14f0685ddcf3a7d64bb85a3e9a9ac97c369bb508 Mon Sep 17 00:00:00 2001
|
diff -ruN a/qelectrotech.pro b/qelectrotech.pro
|
||||||
From: Laurent Trinques <scorpio@qelectrotech.org>
|
--- a/qelectrotech.pro 2023-04-20 11:47:07.695847458 +0200
|
||||||
Date: Sat, 26 Sep 2020 22:52:52 +0200
|
+++ b/qelectrotech.pro 2023-04-20 11:51:14.843611898 +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
|
|
||||||
@@ -5,18 +5,18 @@
|
@@ -5,18 +5,18 @@
|
||||||
# Chemins utilises pour la compilation et l'installation de QET
|
# Chemins utilises pour la compilation et l'installation de QET
|
||||||
unix {
|
unix {
|
||||||
@@ -35,6 +25,3 @@ index 7baddbb08..5dcda04b6 100644
|
|||||||
QET_APPDATA_PATH = 'share/appdata'
|
QET_APPDATA_PATH = 'share/appdata'
|
||||||
}
|
}
|
||||||
win32 {
|
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"]
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -88,6 +88,7 @@ set(QET_RES_FILES
|
|||||||
${QET_DIR}/sources/ui/dynamicelementtextitemeditor.ui
|
${QET_DIR}/sources/ui/dynamicelementtextitemeditor.ui
|
||||||
${QET_DIR}/sources/ui/elementinfopartwidget.ui
|
${QET_DIR}/sources/ui/elementinfopartwidget.ui
|
||||||
${QET_DIR}/sources/ui/elementinfowidget.ui
|
${QET_DIR}/sources/ui/elementinfowidget.ui
|
||||||
|
${QET_DIR}/sources/ui/terminalnumberingdialog.ui
|
||||||
${QET_DIR}/sources/ui/formulaassistantdialog.ui
|
${QET_DIR}/sources/ui/formulaassistantdialog.ui
|
||||||
${QET_DIR}/sources/ui/imagepropertieswidget.ui
|
${QET_DIR}/sources/ui/imagepropertieswidget.ui
|
||||||
${QET_DIR}/sources/ui/importelementdialog.ui
|
${QET_DIR}/sources/ui/importelementdialog.ui
|
||||||
@@ -112,6 +113,8 @@ set(QET_SRC_FILES
|
|||||||
${QET_DIR}/sources/conductorautonumerotation.cpp
|
${QET_DIR}/sources/conductorautonumerotation.cpp
|
||||||
${QET_DIR}/sources/conductorautonumerotation.h
|
${QET_DIR}/sources/conductorautonumerotation.h
|
||||||
${QET_DIR}/sources/conductornumexport.cpp
|
${QET_DIR}/sources/conductornumexport.cpp
|
||||||
|
${QET_DIR}/sources/wiringlistexport.h
|
||||||
|
${QET_DIR}/sources/wiringlistexport.cpp
|
||||||
${QET_DIR}/sources/conductornumexport.h
|
${QET_DIR}/sources/conductornumexport.h
|
||||||
${QET_DIR}/sources/conductorprofile.cpp
|
${QET_DIR}/sources/conductorprofile.cpp
|
||||||
${QET_DIR}/sources/conductorprofile.h
|
${QET_DIR}/sources/conductorprofile.h
|
||||||
@@ -630,6 +633,8 @@ set(QET_SRC_FILES
|
|||||||
${QET_DIR}/sources/ui/elementinfopartwidget.h
|
${QET_DIR}/sources/ui/elementinfopartwidget.h
|
||||||
${QET_DIR}/sources/ui/elementinfowidget.cpp
|
${QET_DIR}/sources/ui/elementinfowidget.cpp
|
||||||
${QET_DIR}/sources/ui/elementinfowidget.h
|
${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.cpp
|
||||||
${QET_DIR}/sources/ui/elementpropertieswidget.h
|
${QET_DIR}/sources/ui/elementpropertieswidget.h
|
||||||
${QET_DIR}/sources/ui/formulaassistantdialog.cpp
|
${QET_DIR}/sources/ui/formulaassistantdialog.cpp
|
||||||
|
|||||||
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -9723,7 +9723,7 @@ Bitte laden Sie diese über den Link herunter und entpacken Sie sie in den Insta
|
|||||||
<message>
|
<message>
|
||||||
<location filename="../sources/ui/terminalnumberingdialog.cpp" line="140"/>
|
<location filename="../sources/ui/terminalnumberingdialog.cpp" line="140"/>
|
||||||
<source>Automatic terminal numbering</source>
|
<source>Automatic terminal numbering</source>
|
||||||
<translation>Automatische Anschlussnummerierung</translation>
|
<translation>Automatische Klemmennummerierung</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|||||||
+364
-186
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+368
-188
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
+364
-186
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ Icon=qelectrotech
|
|||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
MimeType=application/x-qet-project;application/x-qet-element;application/x-qet-titleblock;
|
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;
|
Keywords=Graphics;Science;Electricity;Engineering;
|
||||||
Comment=Edit electrical diagrams.
|
Comment=Edit electrical diagrams.
|
||||||
Comment[ar]=تحرير مخططات كهربائية
|
Comment[ar]=تحرير مخططات كهربائية
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Copyright 2006-2026 The QElectroTech Team -->
|
<!-- Copyright 2006-2026 The QElectroTech Team -->
|
||||||
<application>
|
<component type="desktop-application">
|
||||||
<id type="desktop">qelectrotech.desktop</id>
|
<id>org.qelectrotech.QElectroTech</id>
|
||||||
|
<launchable type="desktop-id">org.qelectrotech.QElectroTech.desktop</launchable>
|
||||||
<metadata_license>MIT</metadata_license>
|
<metadata_license>MIT</metadata_license>
|
||||||
<project_license>GPL-2.0-or-later</project_license>
|
<project_license>GPL-2.0-or-later</project_license>
|
||||||
<name>QElectroTech</name>
|
<name>QElectroTech</name>
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
<summary xml:lang="ru">Редактор электрических схем</summary>
|
<summary xml:lang="ru">Редактор электрических схем</summary>
|
||||||
<content_rating type="oars-1.1"/>
|
<content_rating type="oars-1.1"/>
|
||||||
<releases>
|
<releases>
|
||||||
<release version="0.9-dev" date="2021-02-21"/>
|
<release version="0.100.1-dev" date="2026"/>
|
||||||
</releases>
|
</releases>
|
||||||
<description>
|
<description>
|
||||||
<p>
|
<p>
|
||||||
@@ -93,9 +94,20 @@
|
|||||||
Приложение использует для хранения проектов и библиотек элементов файлы в XML формате. Приложение помимо редактора электричесих схем, содержит также редакторы элементов и редактор шаблонов листов.
|
Приложение использует для хранения проектов и библиотек элементов файлы в XML формате. Приложение помимо редактора электричесих схем, содержит также редакторы элементов и редактор шаблонов листов.
|
||||||
</p>
|
</p>
|
||||||
</description>
|
</description>
|
||||||
<url type="homepage">http://qelectrotech.org</url>
|
<url type="homepage">https://qelectrotech.org</url>
|
||||||
<screenshots>
|
<url type="bugtracker">https://qelectrotech.org/bugtracker</url>
|
||||||
<screenshot type="default">http://download.tuxfamily.org/qet/screens/qelectrotech5.png</screenshot>
|
<url type="vcs-browser">https://github.com/qelectrotech/qelectrotech-source-mirror</url>
|
||||||
</screenshots>
|
<developer id="org.qelectrotech">
|
||||||
<updatecontact>qet@lists.tuxfamily.org</updatecontact>
|
<name>QElectroTech</name>
|
||||||
</application>
|
</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>
|
||||||
|
|||||||
+92
-10
@@ -68,6 +68,9 @@ ElementsPanel::ElementsPanel(QWidget *parent) :
|
|||||||
connect(this, &GenericPanel::firstActivated, [this]() {QTimer::singleShot(250, this, SLOT(reload()));});
|
connect(this, &GenericPanel::firstActivated, [this]() {QTimer::singleShot(250, this, SLOT(reload()));});
|
||||||
connect(this, &ElementsPanel::panelContentChanged, this, &ElementsPanel::panelContentChange);
|
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
|
//Emit a signal instead au manage is own context menu
|
||||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
}
|
}
|
||||||
@@ -139,6 +142,7 @@ QTreeWidgetItem *ElementsPanel::addProject(QETProject *project,
|
|||||||
Q_UNUSED(options)
|
Q_UNUSED(options)
|
||||||
|
|
||||||
bool first_add = (first_reload_ || !projects_to_display_.contains(project));
|
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);
|
QTreeWidgetItem *qtwi_project = GenericPanel::addProject(project, nullptr, GenericPanel::All);
|
||||||
@@ -147,7 +151,17 @@ QTreeWidgetItem *ElementsPanel::addProject(QETProject *project,
|
|||||||
indexOfTopLevelItem(common_tbt_collection_item_),
|
indexOfTopLevelItem(common_tbt_collection_item_),
|
||||||
qtwi_project
|
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 (TitleBlockTemplatesCollection *tbt_collection = project -> embeddedTitleBlockTemplatesCollection()) {
|
||||||
if (QTreeWidgetItem *tbt_collection_qtwi = itemForTemplatesCollection(tbt_collection)) {
|
if (QTreeWidgetItem *tbt_collection_qtwi = itemForTemplatesCollection(tbt_collection)) {
|
||||||
@@ -258,21 +272,28 @@ void ElementsPanel::reload()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gere le double-clic sur un element.
|
@brief ElementsPanel::slot_clicked
|
||||||
Si un double-clic sur un projet est effectue, le signal requestForProject
|
handle click on qtwi
|
||||||
est emis.
|
@param qtwi item that was clickerd on
|
||||||
Si un double-clic sur un schema est effectue, le signal requestForDiagram
|
*/
|
||||||
est emis.
|
void ElementsPanel::slot_clicked(QTreeWidgetItem *clickedItem, int) {
|
||||||
|
|
||||||
|
requestForItem(clickedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ElementsPanel::slot_doubleClick
|
||||||
|
handle double click on qtwi
|
||||||
@param qtwi
|
@param qtwi
|
||||||
*/
|
*/
|
||||||
void ElementsPanel::slot_doubleClick(QTreeWidgetItem *qtwi, int) {
|
void ElementsPanel::slot_doubleClick(QTreeWidgetItem *qtwi, int) {
|
||||||
int qtwi_type = qtwi -> type();
|
int qtwi_type = qtwi -> type();
|
||||||
if (qtwi_type == QET::Project) {
|
if (qtwi_type == QET::Project) {
|
||||||
QETProject *project = valueForItem<QETProject *>(qtwi);
|
// open project properties
|
||||||
emit(requestForProject(project));
|
emit(requestForProjectPropertiesEdition());
|
||||||
} else if (qtwi_type == QET::Diagram) {
|
} else if (qtwi_type == QET::Diagram) {
|
||||||
Diagram *diagram = valueForItem<Diagram *>(qtwi);
|
// open diagram properties
|
||||||
diagram->showMe();
|
emit(requestForDiagramPropertiesEdition());
|
||||||
} else if (qtwi_type == QET::TitleBlockTemplate) {
|
} else if (qtwi_type == QET::TitleBlockTemplate) {
|
||||||
TitleBlockTemplateLocation tbt = valueForItem<TitleBlockTemplateLocation>(qtwi);
|
TitleBlockTemplateLocation tbt = valueForItem<TitleBlockTemplateLocation>(qtwi);
|
||||||
emit(requestForTitleBlockTemplate(tbt));
|
emit(requestForTitleBlockTemplate(tbt));
|
||||||
@@ -444,3 +465,64 @@ void ElementsPanel::ensureHierarchyIsVisible(const QList<QTreeWidgetItem *> &ite
|
|||||||
if (parent_qtwi -> isHidden()) parent_qtwi -> setHidden(false);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,8 +53,13 @@ class ElementsPanel : public GenericPanel {
|
|||||||
signals:
|
signals:
|
||||||
void requestForProject(QETProject *);
|
void requestForProject(QETProject *);
|
||||||
void requestForTitleBlockTemplate(const TitleBlockTemplateLocation &);
|
void requestForTitleBlockTemplate(const TitleBlockTemplateLocation &);
|
||||||
|
// Signal to open the project properties
|
||||||
|
void requestForProjectPropertiesEdition();
|
||||||
|
// Signal to open the diagram properties
|
||||||
|
void requestForDiagramPropertiesEdition();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void slot_clicked(QTreeWidgetItem *, int);
|
||||||
void slot_doubleClick(QTreeWidgetItem *, int);
|
void slot_doubleClick(QTreeWidgetItem *, int);
|
||||||
void reload();
|
void reload();
|
||||||
void filter(const QString &, QET::Filtering = QET::RegularFilter);
|
void filter(const QString &, QET::Filtering = QET::RegularFilter);
|
||||||
@@ -63,6 +68,8 @@ class ElementsPanel : public GenericPanel {
|
|||||||
void buildFilterList();
|
void buildFilterList();
|
||||||
void applyCurrentFilter(const QList<QTreeWidgetItem *> &);
|
void applyCurrentFilter(const QList<QTreeWidgetItem *> &);
|
||||||
void ensureHierarchyIsVisible(const QList<QTreeWidgetItem *> &);
|
void ensureHierarchyIsVisible(const QList<QTreeWidgetItem *> &);
|
||||||
|
void requestForItem(QTreeWidgetItem *);
|
||||||
|
void keyPressEvent(QKeyEvent *event)override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startDrag(Qt::DropActions) override;
|
void startDrag(Qt::DropActions) override;
|
||||||
|
|||||||
@@ -120,6 +120,12 @@ ElementsPanelWidget::ElementsPanelWidget(QWidget *parent) : QWidget(parent) {
|
|||||||
SLOT(openTitleBlockTemplate(const TitleBlockTemplateLocation &))
|
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
|
// disposition verticale
|
||||||
QVBoxLayout *vlayout = new QVBoxLayout(this);
|
QVBoxLayout *vlayout = new QVBoxLayout(this);
|
||||||
vlayout -> setContentsMargins(0,0,0,0);
|
vlayout -> setContentsMargins(0,0,0,0);
|
||||||
@@ -236,6 +242,7 @@ void ElementsPanelWidget::deleteDiagram()
|
|||||||
{
|
{
|
||||||
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
|
if (Diagram *selected_diagram = elements_panel -> selectedDiagram()) {
|
||||||
emit(requestForDiagramDeletion(selected_diagram));
|
emit(requestForDiagramDeletion(selected_diagram));
|
||||||
|
elements_panel->reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -766,7 +766,6 @@ void GenericPanel::projectDiagramsOrderChanged(QETProject *project,
|
|||||||
if (!moved_qtwi_diagram) return;
|
if (!moved_qtwi_diagram) return;
|
||||||
|
|
||||||
// remove the QTWI then insert it back at the adequate location
|
// 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 -> removeChild (moved_qtwi_diagram);
|
||||||
qtwi_project -> insertChild (to, moved_qtwi_diagram);
|
qtwi_project -> insertChild (to, moved_qtwi_diagram);
|
||||||
|
|
||||||
@@ -781,8 +780,8 @@ void GenericPanel::projectDiagramsOrderChanged(QETProject *project,
|
|||||||
updateDiagramItem(qtwi_diagram, diagram);
|
updateDiagramItem(qtwi_diagram, diagram);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (was_selected)
|
// select the moved diagram
|
||||||
setCurrentItem(moved_qtwi_diagram);
|
setCurrentItem(qtwi_project -> child(from));
|
||||||
|
|
||||||
emit(panelContentChanged());
|
emit(panelContentChanged());
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-17
@@ -721,6 +721,14 @@ void ProjectView::initActions()
|
|||||||
|
|
||||||
m_end_view = new QAction(QET::Icons::ArrowRightDouble, tr("Aller à la fin du projet"),this);
|
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());});
|
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);
|
m_tab = new QTabWidget(this);
|
||||||
#endif
|
#endif
|
||||||
m_tab -> setMovable(true);
|
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();
|
QHBoxLayout *TopRightCorner_Layout = new QHBoxLayout();
|
||||||
TopRightCorner_Layout->setContentsMargins(0,0,0,0);
|
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;
|
QHBoxLayout *TopLeftCorner_Layout = new QHBoxLayout();
|
||||||
add_new_diagram_button -> setDefaultAction(m_add_new_diagram);
|
TopLeftCorner_Layout->setContentsMargins(0,0,0,0);
|
||||||
add_new_diagram_button -> setAutoRaise(true);
|
|
||||||
TopRightCorner_Layout->addWidget(add_new_diagram_button);
|
|
||||||
|
|
||||||
connect(m_tab, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
|
// add buttons
|
||||||
connect(m_tab, SIGNAL(tabBarDoubleClicked(int)), this, SLOT(tabDoubleClicked(int)));
|
QToolButton *m_next_right_view_button =new QToolButton;
|
||||||
connect(m_tab->tabBar(), SIGNAL(tabMoved(int, int)), this, SLOT(tabMoved(int, int)), Qt::QueuedConnection);
|
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);
|
||||||
|
|
||||||
//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;
|
QToolButton *m_end_view_button =new QToolButton;
|
||||||
m_end_view_button->setDefaultAction(m_end_view);
|
m_end_view_button->setDefaultAction(m_end_view);
|
||||||
m_end_view_button->setAutoRaise(true);
|
m_end_view_button->setAutoRaise(true);
|
||||||
TopRightCorner_Layout->addWidget(m_end_view_button);
|
TopRightCorner_Layout->addWidget(m_end_view_button);
|
||||||
|
|
||||||
QWidget *tabwidget=new QWidget(this);
|
QToolButton *add_new_diagram_button = new QToolButton;
|
||||||
tabwidget->setLayout(TopRightCorner_Layout);
|
add_new_diagram_button -> setDefaultAction(m_add_new_diagram);
|
||||||
m_tab -> setCornerWidget(tabwidget, Qt::TopRightCorner);
|
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);
|
fallback_widget_ -> setVisible(false);
|
||||||
m_tab -> setVisible(false);
|
m_tab -> setVisible(false);
|
||||||
|
|||||||
@@ -169,7 +169,9 @@ class ProjectView : public QWidget
|
|||||||
private:
|
private:
|
||||||
QAction *m_add_new_diagram,
|
QAction *m_add_new_diagram,
|
||||||
*m_first_view,
|
*m_first_view,
|
||||||
*m_end_view;
|
*m_end_view,
|
||||||
|
*m_next_view_left,
|
||||||
|
*m_next_view_right;
|
||||||
QETProject *m_project;
|
QETProject *m_project;
|
||||||
QVBoxLayout *layout_;
|
QVBoxLayout *layout_;
|
||||||
QWidget *fallback_widget_;
|
QWidget *fallback_widget_;
|
||||||
|
|||||||
@@ -45,6 +45,8 @@
|
|||||||
#include "TerminalStrip/ui/terminalstripeditorwindow.h"
|
#include "TerminalStrip/ui/terminalstripeditorwindow.h"
|
||||||
#include "ui/diagrameditorhandlersizewidget.h"
|
#include "ui/diagrameditorhandlersizewidget.h"
|
||||||
#include "TerminalStrip/ui/addterminalstripitemdialog.h"
|
#include "TerminalStrip/ui/addterminalstripitemdialog.h"
|
||||||
|
#include "wiringlistexport.h"
|
||||||
|
#include "ui/terminalnumberingdialog.h"
|
||||||
|
|
||||||
#ifdef BUILD_WITHOUT_KF5
|
#ifdef BUILD_WITHOUT_KF5
|
||||||
#else
|
#else
|
||||||
@@ -465,13 +467,27 @@ void QETDiagramEditor::setUpActions()
|
|||||||
wne.toCsv();
|
wne.toCsv();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
#ifdef QET_EXPORT_PROJECT_DB
|
// 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);
|
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]() {
|
connect(m_export_project_db, &QAction::triggered, [this]() {
|
||||||
projectDataBase::exportDb(this->currentProject()->dataBase(), this);
|
projectDataBase::exportDb(this->currentProject()->dataBase(), this);
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//MDI view style
|
//MDI view style
|
||||||
m_tabbed_view_mode = new QAction(tr("en utilisant des onglets"), this);
|
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_project_export_conductor_num);
|
||||||
menu_project -> addAction(m_terminal_strip_dialog);
|
menu_project -> addAction(m_terminal_strip_dialog);
|
||||||
menu_project -> addAction(m_project_terminalBloc);
|
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
|
#ifdef QET_EXPORT_PROJECT_DB
|
||||||
menu_project -> addSeparator();
|
menu_project -> addSeparator();
|
||||||
menu_project -> addAction(m_export_project_db);
|
menu_project -> addAction(m_export_project_db);
|
||||||
@@ -1168,18 +1186,6 @@ bool QETDiagramEditor::addProject(QETProject *project, bool update_panel)
|
|||||||
|
|
||||||
// cree un ProjectView pour visualiser le projet
|
// cree un ProjectView pour visualiser le projet
|
||||||
ProjectView *project_view = new ProjectView(project);
|
ProjectView *project_view = new ProjectView(project);
|
||||||
//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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addProjectView(project_view);
|
addProjectView(project_view);
|
||||||
|
|
||||||
undo_group.addStack(project -> undoStack());
|
undo_group.addStack(project -> undoStack());
|
||||||
@@ -1579,6 +1585,8 @@ void QETDiagramEditor::slot_updateActions()
|
|||||||
m_csv_export -> setEnabled(editable_project);
|
m_csv_export -> setEnabled(editable_project);
|
||||||
m_project_export_conductor_num-> setEnabled(opened_project);
|
m_project_export_conductor_num-> setEnabled(opened_project);
|
||||||
m_terminal_strip_dialog -> setEnabled(editable_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
|
#ifdef QET_EXPORT_PROJECT_DB
|
||||||
m_export_project_db -> setEnabled(editable_project);
|
m_export_project_db -> setEnabled(editable_project);
|
||||||
#endif
|
#endif
|
||||||
@@ -1840,6 +1848,31 @@ void QETDiagramEditor::addProjectView(ProjectView *project_view)
|
|||||||
connect(project_view, SIGNAL(errorEncountered(QString)),
|
connect(project_view, SIGNAL(errorEncountered(QString)),
|
||||||
this, SLOT(showError(const 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
|
//We maximise the new window if the current window is inexistent or maximized
|
||||||
QWidget *current_window = m_workspace.activeSubWindow();
|
QWidget *current_window = m_workspace.activeSubWindow();
|
||||||
bool maximise = ((!current_window)
|
bool maximise = ((!current_window)
|
||||||
@@ -2348,6 +2381,7 @@ void QETDiagramEditor::subWindowActivated(QMdiSubWindow *subWindows)
|
|||||||
|
|
||||||
slot_updateActions();
|
slot_updateActions();
|
||||||
slot_updateWindowsMenu();
|
slot_updateWindowsMenu();
|
||||||
|
emit syncElementsPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2487,3 +2521,23 @@ void QETDiagramEditor::generateTerminalBlock()
|
|||||||
message);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class RecentFiles;
|
|||||||
class DiagramPropertiesEditorDockWidget;
|
class DiagramPropertiesEditorDockWidget;
|
||||||
class ElementsCollectionWidget;
|
class ElementsCollectionWidget;
|
||||||
class AutoNumberingDockWidget;
|
class AutoNumberingDockWidget;
|
||||||
|
class TerminalNumberingDialog;
|
||||||
|
|
||||||
#ifdef BUILD_WITHOUT_KF5
|
#ifdef BUILD_WITHOUT_KF5
|
||||||
#else
|
#else
|
||||||
@@ -98,6 +99,9 @@ class QETDiagramEditor : public QETMainWindow
|
|||||||
ProjectView *findProject(const QString &) const;
|
ProjectView *findProject(const QString &) const;
|
||||||
QMdiSubWindow *subWindowForWidget(QWidget *) const;
|
QMdiSubWindow *subWindowForWidget(QWidget *) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void syncElementsPanel();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void save();
|
void save();
|
||||||
void saveAs();
|
void saveAs();
|
||||||
@@ -129,6 +133,7 @@ class QETDiagramEditor : public QETMainWindow
|
|||||||
void projectWasClosed(ProjectView *);
|
void projectWasClosed(ProjectView *);
|
||||||
void editProjectProperties(ProjectView *);
|
void editProjectProperties(ProjectView *);
|
||||||
void editProjectProperties(QETProject *);
|
void editProjectProperties(QETProject *);
|
||||||
|
void slot_terminalNumbering();
|
||||||
void editDiagramProperties(DiagramView *);
|
void editDiagramProperties(DiagramView *);
|
||||||
void editDiagramProperties(Diagram *);
|
void editDiagramProperties(Diagram *);
|
||||||
void addDiagramToProject(QETProject *);
|
void addDiagramToProject(QETProject *);
|
||||||
@@ -197,6 +202,8 @@ class QETDiagramEditor : public QETMainWindow
|
|||||||
*m_terminal_strip_dialog = nullptr, ///<Launch terminal strip dialog
|
*m_terminal_strip_dialog = nullptr, ///<Launch terminal strip dialog
|
||||||
*m_project_terminalBloc, ///< generate terminal block
|
*m_project_terminalBloc, ///< generate terminal block
|
||||||
*m_project_export_conductor_num,///<Export the wire num to csv
|
*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_export_project_db, ///Export to file the internal database of the current project
|
||||||
*m_tile_window, ///< Show MDI subwindows as tile
|
*m_tile_window, ///< Show MDI subwindows as tile
|
||||||
*m_cascade_window, ///< Show MDI subwindows as cascade
|
*m_cascade_window, ///< Show MDI subwindows as cascade
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ void ElementInfoWidget::enableLiveEdit()
|
|||||||
{
|
{
|
||||||
for (ElementInfoPartWidget *eipw : m_eipw_list)
|
for (ElementInfoPartWidget *eipw : m_eipw_list)
|
||||||
connect(eipw, &ElementInfoPartWidget::textChanged, this, &ElementInfoWidget::apply);
|
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)
|
for (ElementInfoPartWidget *eipw : m_eipw_list)
|
||||||
disconnect(eipw, &ElementInfoPartWidget::textChanged, this, &ElementInfoWidget::apply);
|
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();
|
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) {
|
for (ElementInfoPartWidget *eipw : m_eipw_list) {
|
||||||
eipw -> setText (element_info[eipw->key()].toString());
|
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) {
|
if (m_live_edit) {
|
||||||
enableLiveEdit();
|
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_;
|
return info_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,19 @@
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</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>
|
<item>
|
||||||
<widget class="QScrollArea" name="scrollArea">
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
|||||||
@@ -372,6 +372,10 @@ QWidget *ElementPropertiesWidget::generalWidget()
|
|||||||
description_string += QString(tr("Rotation : %1°\n")).arg(m_element.data()->rotation());
|
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("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());
|
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());
|
description_string += QString(tr("Emplacement : %1\n")).arg(m_element.data()->location().toString());
|
||||||
|
|
||||||
// widget himself
|
// widget himself
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ void MasterPropertiesWidget::on_link_button_clicked()
|
|||||||
// Show a message box with the actual window as parent to ensure it's on top
|
// Show a message box with the actual window as parent to ensure it's on top
|
||||||
QMessageBox::warning(this->window(),
|
QMessageBox::warning(this->window(),
|
||||||
tr("Nombre maximal d'esclaves atteint."),
|
tr("Nombre maximal d'esclaves atteint."),
|
||||||
tr("Cet élément maître ne peut accepter aucun nouvel esclave car il est plein (Limit: %1).").arg(max_slaves));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>TerminalNumberingDialog</class>
|
||||||
|
<widget class="QDialog" name="TerminalNumberingDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Numérotation automatique des bornes</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_description">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cette fonction numérote les bornes du projet selon leur position. Les bornes vides ou verrouillées sont ignorées.Le marquage des bornes doit être configuré au préalable comme suit : '-X:AB'. La partie avant les deux-points (le bornier) peut être nommée au choix. 'AB' peut être composé de chiffres ou de lettres."</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_axis">
|
||||||
|
<property name="title">
|
||||||
|
<string>Priorité des axes</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rb_priority_x">
|
||||||
|
<property name="text">
|
||||||
|
<string>Priorité à l'axe X (horizontal)</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rb_priority_y">
|
||||||
|
<property name="text">
|
||||||
|
<string>Priorité à l'axe Y (vertical)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_type">
|
||||||
|
<property name="title">
|
||||||
|
<string>Type de numérotation</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rb_type_num">
|
||||||
|
<property name="text">
|
||||||
|
<string>Numérique uniquement (1, 2, 3...)</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rb_type_alpha">
|
||||||
|
<property name="text">
|
||||||
|
<string>Alphanumérique (A, B, C... 1, 2...)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>TerminalNumberingDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>TerminalNumberingDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
#include "wiringlistexport.h"
|
||||||
|
#include "qetproject.h"
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QQueue>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
|
WiringListExport::WiringListExport(QETProject *project, QWidget *parent) :
|
||||||
|
QObject(parent),
|
||||||
|
m_project(project),
|
||||||
|
m_parent(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString WiringListExport::normalizeUuid(const QString &u) const
|
||||||
|
{
|
||||||
|
QString res = u;
|
||||||
|
res.remove('{').remove('}');
|
||||||
|
return res.trimmed().toLower();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString WiringListExport::findDiagramFolio(const QDomElement &diagramElem) const
|
||||||
|
{
|
||||||
|
if (diagramElem.isNull()) return "";
|
||||||
|
if (diagramElem.hasAttribute("folio")) return diagramElem.attribute("folio");
|
||||||
|
if (diagramElem.hasAttribute("title")) return diagramElem.attribute("title");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement WiringListExport::climbToDiagram(QDomNode node) const
|
||||||
|
{
|
||||||
|
while (!node.isNull()) {
|
||||||
|
if (node.isElement() && node.toElement().tagName().toLower() == "diagram") {
|
||||||
|
return node.toElement();
|
||||||
|
}
|
||||||
|
node = node.parentNode();
|
||||||
|
}
|
||||||
|
return QDomElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, ElementInfo> WiringListExport::collectElementsInfo(const QDomElement &root) const
|
||||||
|
{
|
||||||
|
QMap<QString, ElementInfo> infoMap;
|
||||||
|
QDomNodeList elements = root.elementsByTagName("element");
|
||||||
|
|
||||||
|
for (int i = 0; i < elements.size(); ++i) {
|
||||||
|
QDomElement el = elements.at(i).toElement();
|
||||||
|
QString uuid = normalizeUuid(el.attribute("uuid", el.attribute("id", "")));
|
||||||
|
if (uuid.isEmpty()) continue;
|
||||||
|
|
||||||
|
ElementInfo info;
|
||||||
|
info.folio = findDiagramFolio(climbToDiagram(el));
|
||||||
|
|
||||||
|
QDomElement linksNode = el.firstChildElement("links_uuids");
|
||||||
|
if (!linksNode.isNull()) {
|
||||||
|
QDomNodeList linkUuids = linksNode.elementsByTagName("link_uuid");
|
||||||
|
for (int j = 0; j < linkUuids.size(); ++j) {
|
||||||
|
QString luuid = normalizeUuid(linkUuids.at(j).toElement().attribute("uuid"));
|
||||||
|
if (!luuid.isEmpty()) info.links.append(luuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement elInfoNode = el.firstChildElement("elementInformations");
|
||||||
|
if (!elInfoNode.isNull()) {
|
||||||
|
QDomNodeList eics = elInfoNode.elementsByTagName("elementInformation");
|
||||||
|
for (int j = 0; j < eics.size(); ++j) {
|
||||||
|
QDomElement eic = eics.at(j).toElement();
|
||||||
|
QString nameAttr = eic.attribute("name").toLower();
|
||||||
|
if (nameAttr == "label") info.label = eic.text().trimmed();
|
||||||
|
if (nameAttr == "name") info.name = eic.text().trimmed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString typeVal = el.attribute("type").toLower();
|
||||||
|
if (typeVal.contains("naechste") || typeVal.contains("vorherige") ||
|
||||||
|
typeVal.contains("next") || typeVal.contains("previous")) {
|
||||||
|
info.isPlaceholder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
infoMap.insert(uuid, info);
|
||||||
|
}
|
||||||
|
return infoMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ConductorData> WiringListExport::collectConductors(const QDomElement &root) const
|
||||||
|
{
|
||||||
|
QList<ConductorData> conductors;
|
||||||
|
QDomNodeList conductorNodes = root.elementsByTagName("conductor");
|
||||||
|
|
||||||
|
for (int i = 0; i < conductorNodes.size(); ++i) {
|
||||||
|
QDomElement cond = conductorNodes.at(i).toElement();
|
||||||
|
|
||||||
|
if (cond.attribute("num") == "Brücke") continue;
|
||||||
|
|
||||||
|
ConductorData data;
|
||||||
|
data.index = i;
|
||||||
|
data.el1_uuid = normalizeUuid(cond.attribute("element1", cond.attribute("element1id", "")));
|
||||||
|
data.el2_uuid = normalizeUuid(cond.attribute("element2", cond.attribute("element2id", "")));
|
||||||
|
|
||||||
|
data.element1_label = cond.attribute("element1_label");
|
||||||
|
data.element2_label = cond.attribute("element2_label");
|
||||||
|
data.terminalname1 = cond.attribute("terminalname1");
|
||||||
|
data.terminalname2 = cond.attribute("terminalname2");
|
||||||
|
data.tension_protocol = cond.attribute("tension_protocol");
|
||||||
|
data.conductor_color = cond.attribute("conductor_color");
|
||||||
|
data.conductor_section = cond.attribute("conductor_section");
|
||||||
|
data.function = cond.attribute("function");
|
||||||
|
|
||||||
|
QDomElement diag = climbToDiagram(cond);
|
||||||
|
data.folio = findDiagramFolio(diag);
|
||||||
|
if (data.folio.isEmpty()) data.folio = cond.attribute("folio", cond.attribute("page", ""));
|
||||||
|
|
||||||
|
conductors.append(data);
|
||||||
|
}
|
||||||
|
return conductors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiringListExport::resolveEndpoints(QList<ConductorData> &conductors, const QMap<QString, ElementInfo> &elementsInfo) const
|
||||||
|
{
|
||||||
|
QRegularExpression numericLabelRe("^\\d+(\\.\\d+)?$");
|
||||||
|
|
||||||
|
QMap<QString, QList<ConductorData>> el_to_cons;
|
||||||
|
for (const ConductorData &c : conductors) {
|
||||||
|
if (!c.el1_uuid.isEmpty()) el_to_cons[c.el1_uuid].append(c);
|
||||||
|
if (!c.el2_uuid.isEmpty()) el_to_cons[c.el2_uuid].append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < conductors.size(); ++i) {
|
||||||
|
ConductorData &c = conductors[i];
|
||||||
|
|
||||||
|
auto resolveSide = [&](const QString &startUuid, QString &outLabel, QString &outTerminal) {
|
||||||
|
if (startUuid.isEmpty() || !elementsInfo.contains(startUuid)) return;
|
||||||
|
|
||||||
|
const ElementInfo &startInfo = elementsInfo[startUuid];
|
||||||
|
if (!startInfo.links.isEmpty() || startInfo.isPlaceholder) {
|
||||||
|
QQueue<QString> q;
|
||||||
|
QSet<QString> visited;
|
||||||
|
q.enqueue(startUuid);
|
||||||
|
visited.insert(startUuid);
|
||||||
|
|
||||||
|
int depth = 0;
|
||||||
|
while (!q.isEmpty() && depth < 3) {
|
||||||
|
int levelSize = q.size();
|
||||||
|
for (int k = 0; k < levelSize; ++k) {
|
||||||
|
QString curr = q.dequeue();
|
||||||
|
|
||||||
|
if (elementsInfo.contains(curr)) {
|
||||||
|
const ElementInfo &currInfo = elementsInfo[curr];
|
||||||
|
|
||||||
|
if (!currInfo.isPlaceholder && !currInfo.label.isEmpty() && !numericLabelRe.match(currInfo.label).hasMatch()) {
|
||||||
|
outLabel = currInfo.label;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QString &lnk : currInfo.links) {
|
||||||
|
if (!visited.contains(lnk)) {
|
||||||
|
visited.insert(lnk);
|
||||||
|
q.enqueue(lnk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const ConductorData &cond : el_to_cons.value(curr)) {
|
||||||
|
if (cond.index == c.index) continue;
|
||||||
|
|
||||||
|
QString other;
|
||||||
|
QString terminalHint;
|
||||||
|
if (cond.el1_uuid == curr) {
|
||||||
|
other = cond.el2_uuid;
|
||||||
|
terminalHint = cond.terminalname2;
|
||||||
|
} else {
|
||||||
|
other = cond.el1_uuid;
|
||||||
|
terminalHint = cond.terminalname1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!other.isEmpty() && !visited.contains(other)) {
|
||||||
|
if (elementsInfo.contains(other)) {
|
||||||
|
const ElementInfo &oInfo = elementsInfo[other];
|
||||||
|
if (!oInfo.isPlaceholder && !oInfo.label.isEmpty() && !numericLabelRe.match(oInfo.label).hasMatch()) {
|
||||||
|
outLabel = oInfo.label;
|
||||||
|
if (outTerminal.isEmpty()) outTerminal = terminalHint;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visited.insert(other);
|
||||||
|
q.enqueue(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (outLabel.isEmpty()) {
|
||||||
|
outLabel = startInfo.label.isEmpty() ? startInfo.name : startInfo.label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool p1 = elementsInfo.value(c.el1_uuid).isPlaceholder;
|
||||||
|
bool p2 = elementsInfo.value(c.el2_uuid).isPlaceholder;
|
||||||
|
|
||||||
|
if (c.element1_label.isEmpty() || p1) {
|
||||||
|
if (p1) c.element1_label = "";
|
||||||
|
resolveSide(c.el1_uuid, c.element1_label, c.terminalname1);
|
||||||
|
}
|
||||||
|
if (c.element2_label.isEmpty() || p2) {
|
||||||
|
if (p2) c.element2_label = "";
|
||||||
|
resolveSide(c.el2_uuid, c.element2_label, c.terminalname2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiringListExport::toCsv()
|
||||||
|
{
|
||||||
|
if (!m_project) return;
|
||||||
|
|
||||||
|
QDomDocument doc = m_project->toXml();
|
||||||
|
|
||||||
|
if (doc.isNull()) {
|
||||||
|
QMessageBox::warning(m_parent, tr("Erreur"), tr("Impossible de lire la structure en mémoire du projet."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileDialog dialog(m_parent);
|
||||||
|
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
dialog.setWindowTitle(tr("Exporter le plan de câblage"));
|
||||||
|
dialog.setDefaultSuffix("csv");
|
||||||
|
dialog.setNameFilter(tr("Fichiers CSV (*.csv)"));
|
||||||
|
|
||||||
|
if (dialog.exec() != QDialog::Accepted) return;
|
||||||
|
QString fileName = dialog.selectedFiles().first();
|
||||||
|
|
||||||
|
QFile file(fileName);
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
QMessageBox::warning(m_parent, tr("Erreur"), tr("Impossible d'ouvrir le fichier pour l'écriture."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, ElementInfo> elementsInfo = collectElementsInfo(doc.documentElement());
|
||||||
|
QList<ConductorData> conductors = collectConductors(doc.documentElement());
|
||||||
|
|
||||||
|
resolveEndpoints(conductors, elementsInfo);
|
||||||
|
|
||||||
|
QList<ConductorData> uniqueConductors;
|
||||||
|
QSet<QString> seenConnections;
|
||||||
|
|
||||||
|
for (const ConductorData &c : conductors) {
|
||||||
|
if (c.element1_label.isEmpty() && c.element2_label.isEmpty()) continue;
|
||||||
|
|
||||||
|
QString sideA = c.element1_label + ":" + c.terminalname1;
|
||||||
|
QString sideB = c.element2_label + ":" + c.terminalname2;
|
||||||
|
|
||||||
|
QString key = (sideA < sideB) ? (sideA + "||" + sideB) : (sideB + "||" + sideA);
|
||||||
|
|
||||||
|
if (!seenConnections.contains(key)) {
|
||||||
|
seenConnections.insert(key);
|
||||||
|
uniqueConductors.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream out(&file);
|
||||||
|
out << tr("Page", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Composant 1", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Borne 1", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Composant 2", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Borne 2", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Tension / Protocole", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Couleur du fil", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Section du fil", "Wiring list CSV header") << ";"
|
||||||
|
<< tr("Fonction", "Wiring list CSV header") << "\n";
|
||||||
|
|
||||||
|
for (const ConductorData &c : uniqueConductors) {
|
||||||
|
out << c.folio << ";"
|
||||||
|
<< c.element1_label << ";"
|
||||||
|
<< c.terminalname1 << ";"
|
||||||
|
<< c.element2_label << ";"
|
||||||
|
<< c.terminalname2 << ";"
|
||||||
|
<< c.tension_protocol << ";"
|
||||||
|
<< c.conductor_color << ";"
|
||||||
|
<< c.conductor_section << ";"
|
||||||
|
<< c.function << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
QMessageBox::information(m_parent, tr("Export réussi"), tr("Le plan de câblage a été exporté avec succès !"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#ifndef WIRINGLISTEXPORT_H
|
||||||
|
#define WIRINGLISTEXPORT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QList>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class QETProject;
|
||||||
|
class QWidget;
|
||||||
|
class QDomElement;
|
||||||
|
class QDomNode;
|
||||||
|
|
||||||
|
// Internal data structures for parsing the XML graph
|
||||||
|
struct ElementInfo {
|
||||||
|
QString folio;
|
||||||
|
QStringList links;
|
||||||
|
QString label;
|
||||||
|
QString name;
|
||||||
|
bool isPlaceholder = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConductorData {
|
||||||
|
int index = 0;
|
||||||
|
QString el1_uuid;
|
||||||
|
QString el2_uuid;
|
||||||
|
QString element1_label;
|
||||||
|
QString element2_label;
|
||||||
|
QString terminalname1;
|
||||||
|
QString terminalname2;
|
||||||
|
QString tension_protocol;
|
||||||
|
QString conductor_color;
|
||||||
|
QString conductor_section;
|
||||||
|
QString function;
|
||||||
|
QString folio;
|
||||||
|
|
||||||
|
// Resolved endpoints
|
||||||
|
QString chosen_a_uuid;
|
||||||
|
QString chosen_a_label;
|
||||||
|
QString chosen_b_uuid;
|
||||||
|
QString chosen_b_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The WiringListExport class
|
||||||
|
* Handles the export of the wiring list (Verdrahtungsplan) to a CSV file.
|
||||||
|
* Automatically resolves links and placeholders to find physical endpoints.
|
||||||
|
*/
|
||||||
|
class WiringListExport : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit WiringListExport(QETProject *project, QWidget *parent = nullptr);
|
||||||
|
void toCsv();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QETProject *m_project;
|
||||||
|
QWidget *m_parent;
|
||||||
|
|
||||||
|
QString normalizeUuid(const QString &u) const;
|
||||||
|
QString findDiagramFolio(const QDomElement &diagramElem) const;
|
||||||
|
QDomElement climbToDiagram(QDomNode node) const;
|
||||||
|
|
||||||
|
QMap<QString, ElementInfo> collectElementsInfo(const QDomElement &root) const;
|
||||||
|
QList<ConductorData> collectConductors(const QDomElement &root) const;
|
||||||
|
|
||||||
|
void resolveEndpoints(QList<ConductorData> &conductors, const QMap<QString, ElementInfo> &elementsInfo) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIRINGLISTEXPORT_H
|
||||||
Reference in New Issue
Block a user