mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-06-10 04:43:15 +02:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 34eb6e9f71 | |||
| faf4235bed | |||
| 0a51e22b7d | |||
| 632fba5366 | |||
| 0ca883f114 | |||
| 170d856007 | |||
| 0424eb9fba | |||
| 8210f06919 | |||
| 468618adda | |||
| 8141a75738 | |||
| 8f201a6e5d | |||
| b8745c0a6b | |||
| 7c3bde9118 | |||
| 28cd389695 | |||
| 56bb2a399b | |||
| dc726792d3 | |||
| d8707a4ef2 | |||
| 77710e1cc5 | |||
| 1d2c00819d | |||
| eee0469bd7 | |||
| 5118037cb5 | |||
| 1f53c39290 | |||
| b71aec9548 | |||
| c7798e1a80 | |||
| f97edad75a | |||
| 454b2c8a0f | |||
| b2782bc460 | |||
| 059f0eb1b6 | |||
| ce318ac667 | |||
| be2067148e | |||
| 444f62a1f8 | |||
| 8f85cacb06 | |||
| ffe3d98279 | |||
| dea926e4b4 | |||
| a1779d1a7a | |||
| 252106178b | |||
| a00404bc9f | |||
| e2ebb445a8 | |||
| 24ec94d73e | |||
| edb42caa16 | |||
| c110acc0ac | |||
| 3467c09c1e |
+1
-1
@@ -19,7 +19,7 @@ include(cmake/hoto_update_cmake_message.cmake)
|
|||||||
cmake_minimum_required(VERSION 3.14...3.19 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.14...3.19 FATAL_ERROR)
|
||||||
|
|
||||||
project(qelectrotech
|
project(qelectrotech
|
||||||
VERSION 0.8.0
|
VERSION 0.9.0
|
||||||
DESCRIPTION "QET is a CAD/CAE editor focusing on schematics drawing features."
|
DESCRIPTION "QET is a CAD/CAE editor focusing on schematics drawing features."
|
||||||
HOMEPAGE_URL "https://qelectrotech.org/"
|
HOMEPAGE_URL "https://qelectrotech.org/"
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|||||||
@@ -1,12 +1,79 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
If by accident I have forgotten to credit someone in the CHANGELOG, email me and I will fix it.
|
||||||
|
|
||||||
|
__3.2.0__
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Added support for Qt 6 - _Jonas Kvinge_
|
||||||
|
* Fixed warning in `Qt 5.9` with `min`/`max` functions on Windows - _Nick Korotysh_
|
||||||
|
* Fix return value of connectToPrimary() when connect is successful - _Jonas Kvinge_
|
||||||
|
* Fix build issue with MinGW GCC pedantic mode - _Iakov Kirilenko_
|
||||||
|
* Fixed conversion from `int` to `quint32` and Clang Tidy warnings - _Hennadii Chernyshchyk_
|
||||||
|
|
||||||
|
__3.1.5__
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Improved library stability in edge cases and very rapid process initialisation
|
||||||
|
* Fixed Bug where the shared memory block may have been modified without a lock
|
||||||
|
* Fixed Bug causing `instanceStarted()` to not get emitted when a second instance
|
||||||
|
has been started before the primary has initiated it's `QLocalServer`.
|
||||||
|
|
||||||
|
__3.1.4__
|
||||||
|
---------
|
||||||
|
* Officially supporting and build-testing against Qt 5.15
|
||||||
|
* Fixed an MSVC C4996 warning that suggests using `strncpy_s`.
|
||||||
|
|
||||||
|
_Hennadii Chernyshchyk_
|
||||||
|
|
||||||
|
__3.1.3.1__
|
||||||
|
---------
|
||||||
|
* CMake build system improvements
|
||||||
|
* Fixed Clang Tidy warnings
|
||||||
|
|
||||||
|
_Hennadii Chernyshchyk_
|
||||||
|
|
||||||
|
__3.1.3__
|
||||||
|
---------
|
||||||
|
* Improved `CMakeLists.txt`
|
||||||
|
|
||||||
|
_Hennadii Chernyshchyk_
|
||||||
|
|
||||||
|
__3.1.2__
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Fix a crash when exiting an application on Android and iOS
|
||||||
|
|
||||||
|
_Emeric Grange_
|
||||||
|
|
||||||
|
__3.1.1a__
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Added currentUser() method that returns the user the current instance is running as.
|
||||||
|
|
||||||
|
_Leander Schulten_
|
||||||
|
|
||||||
|
__3.1.0a__
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Added primaryUser() method that returns the user the primary instance is running as.
|
||||||
|
|
||||||
|
__3.0.19__
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Fixed code warning for depricated functions in Qt 5.10 related to `QTime` and `qrand()`.
|
||||||
|
|
||||||
|
_Hennadii Chernyshchyk_
|
||||||
|
_Anton Filimonov_
|
||||||
|
_Jonas Kvinge_
|
||||||
|
|
||||||
__3.0.18__
|
__3.0.18__
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* Fallback to standard QApplication class on iOS and Android systems where
|
* Fallback to standard QApplication class on iOS and Android systems where
|
||||||
the library is not supported.
|
the library is not supported.
|
||||||
|
|
||||||
* Added Build CI tests to verify the library builds successfully on Linux, Windows and MacOS across multiple Qt versions.
|
* Added Build CI tests to verify the library builds successfully on Linux, Windows and MacOS across multiple Qt versions.
|
||||||
|
|
||||||
_Anton Filimonov_
|
_Anton Filimonov_
|
||||||
|
|||||||
@@ -1,43 +1,40 @@
|
|||||||
cmake_minimum_required(VERSION 3.1.0)
|
cmake_minimum_required(VERSION 3.7.0)
|
||||||
|
|
||||||
project(SingleApplication)
|
project(SingleApplication LANGUAGES CXX)
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
# SingleApplication base class
|
|
||||||
set(QAPPLICATION_CLASS QCoreApplication CACHE STRING "Inheritance class for SingleApplication")
|
|
||||||
set_property(CACHE QAPPLICATION_CLASS PROPERTY STRINGS QApplication QGuiApplication QCoreApplication)
|
|
||||||
|
|
||||||
# Libary target
|
|
||||||
add_library(${PROJECT_NAME} STATIC
|
add_library(${PROJECT_NAME} STATIC
|
||||||
singleapplication.cpp
|
singleapplication.cpp
|
||||||
singleapplication_p.cpp
|
singleapplication_p.cpp
|
||||||
)
|
)
|
||||||
|
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||||
|
|
||||||
|
if(NOT QT_DEFAULT_MAJOR_VERSION)
|
||||||
|
set(QT_DEFAULT_MAJOR_VERSION 5 CACHE STRING "Qt version to use (5 or 6), defaults to 5")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Find dependencies
|
# Find dependencies
|
||||||
find_package(Qt5Network)
|
set(QT_COMPONENTS Core Network)
|
||||||
if(QAPPLICATION_CLASS STREQUAL QApplication)
|
set(QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Network)
|
||||||
find_package(Qt5 COMPONENTS Widgets REQUIRED)
|
|
||||||
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
|
|
||||||
find_package(Qt5 COMPONENTS Gui REQUIRED)
|
|
||||||
else()
|
|
||||||
find_package(Qt5 COMPONENTS Core REQUIRED)
|
|
||||||
endif()
|
|
||||||
add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
|
|
||||||
|
|
||||||
# Link dependencies
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Network)
|
|
||||||
if(QAPPLICATION_CLASS STREQUAL QApplication)
|
if(QAPPLICATION_CLASS STREQUAL QApplication)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)
|
list(APPEND QT_COMPONENTS Widgets)
|
||||||
|
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Widgets)
|
||||||
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
|
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui)
|
list(APPEND QT_COMPONENTS Gui)
|
||||||
|
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Gui)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core)
|
set(QAPPLICATION_CLASS QCoreApplication)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${QT_LIBRARIES})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE advapi32)
|
target_link_libraries(${PROJECT_NAME} PRIVATE advapi32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PUBLIC QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) Itay Grudev 2015 - 2016
|
Copyright (c) Itay Grudev 2015 - 2020
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
+45
-18
@@ -1,7 +1,8 @@
|
|||||||
SingleApplication
|
SingleApplication
|
||||||
=================
|
=================
|
||||||
|
[](https://github.com/itay-grudev/SingleApplication/actions)
|
||||||
|
|
||||||
This is a replacement of the QtSingleApplication for `Qt5`.
|
This is a replacement of the QtSingleApplication for `Qt5` and `Qt6`.
|
||||||
|
|
||||||
Keeps the Primary Instance of your Application and kills each subsequent
|
Keeps the Primary Instance of your Application and kills each subsequent
|
||||||
instances. It can (if enabled) spawn secondary (non-related to the primary)
|
instances. It can (if enabled) spawn secondary (non-related to the primary)
|
||||||
@@ -15,18 +16,6 @@ class you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the
|
|||||||
default). Further usage is similar to the use of the `Q[Core|Gui]Application`
|
default). Further usage is similar to the use of the `Q[Core|Gui]Application`
|
||||||
classes.
|
classes.
|
||||||
|
|
||||||
The library sets up a `QLocalServer` and a `QSharedMemory` block. The first
|
|
||||||
instance of your Application is your Primary Instance. It would check if the
|
|
||||||
shared memory block exists and if not it will start a `QLocalServer` and listen
|
|
||||||
for connections. Each subsequent instance of your application would check if the
|
|
||||||
shared memory block exists and if it does, it will connect to the QLocalServer
|
|
||||||
to notify the primary instance that a new instance had been started, after which
|
|
||||||
it would terminate with status code `0`. In the Primary Instance
|
|
||||||
`SingleApplication` would emit the `instanceStarted()` signal upon detecting
|
|
||||||
that a new instance had been started.
|
|
||||||
|
|
||||||
The library uses `stdlib` to terminate the program with the `exit()` function.
|
|
||||||
|
|
||||||
You can use the library as if you use any other `QCoreApplication` derived
|
You can use the library as if you use any other `QCoreApplication` derived
|
||||||
class:
|
class:
|
||||||
|
|
||||||
@@ -43,8 +32,7 @@ int main( int argc, char* argv[] )
|
|||||||
```
|
```
|
||||||
|
|
||||||
To include the library files I would recommend that you add it as a git
|
To include the library files I would recommend that you add it as a git
|
||||||
submodule to your project and include it's contents with a `.pri` file. Here is
|
submodule to your project. Here is how:
|
||||||
how:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication
|
git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication
|
||||||
@@ -66,13 +54,27 @@ Then include the subdirectory in your `CMakeLists.txt` project file.
|
|||||||
```cmake
|
```cmake
|
||||||
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
|
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
|
||||||
add_subdirectory(src/third-party/singleapplication)
|
add_subdirectory(src/third-party/singleapplication)
|
||||||
|
target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The library sets up a `QLocalServer` and a `QSharedMemory` block. The first
|
||||||
|
instance of your Application is your Primary Instance. It would check if the
|
||||||
|
shared memory block exists and if not it will start a `QLocalServer` and listen
|
||||||
|
for connections. Each subsequent instance of your application would check if the
|
||||||
|
shared memory block exists and if it does, it will connect to the QLocalServer
|
||||||
|
to notify the primary instance that a new instance had been started, after which
|
||||||
|
it would terminate with status code `0`. In the Primary Instance
|
||||||
|
`SingleApplication` would emit the `instanceStarted()` signal upon detecting
|
||||||
|
that a new instance had been started.
|
||||||
|
|
||||||
|
The library uses `stdlib` to terminate the program with the `exit()` function.
|
||||||
|
|
||||||
Also don't forget to specify which `QCoreApplication` class your app is using if it
|
Also don't forget to specify which `QCoreApplication` class your app is using if it
|
||||||
is not `QCoreApplication` as in examples above.
|
is not `QCoreApplication` as in examples above.
|
||||||
|
|
||||||
The `Instance Started` signal
|
The `Instance Started` signal
|
||||||
------------------------
|
-----------------------------
|
||||||
|
|
||||||
The SingleApplication class implements a `instanceStarted()` signal. You can
|
The SingleApplication class implements a `instanceStarted()` signal. You can
|
||||||
bind to that signal to raise your application's window when a new instance had
|
bind to that signal to raise your application's window when a new instance had
|
||||||
@@ -137,13 +139,22 @@ app.isSecondary();
|
|||||||
*__Note:__ If your Primary Instance is terminated a newly launched instance
|
*__Note:__ If your Primary Instance is terminated a newly launched instance
|
||||||
will replace the Primary one even if the Secondary flag has been set.*
|
will replace the Primary one even if the Secondary flag has been set.*
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
There are three examples provided in this repository:
|
||||||
|
|
||||||
|
* Basic example that prevents a secondary instance from starting [`examples/basic`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/basic)
|
||||||
|
* An example of a graphical application raising it's parent window [`examples/calculator`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/calculator)
|
||||||
|
* A console application sending the primary instance it's command line parameters [`examples/sending_arguments`](https://github.com/itay-grudev/SingleApplication/tree/master/examples/sending_arguments)
|
||||||
|
|
||||||
API
|
API
|
||||||
---
|
---
|
||||||
|
|
||||||
### Members
|
### Members
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 )
|
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100, QString userData = QString() )
|
||||||
```
|
```
|
||||||
|
|
||||||
Depending on whether `allowSecondary` is set, this constructor may terminate
|
Depending on whether `allowSecondary` is set, this constructor may terminate
|
||||||
@@ -152,7 +163,7 @@ can be specified to set whether the SingleApplication block should work
|
|||||||
user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be
|
user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be
|
||||||
used to notify the primary instance whenever a secondary instance had been
|
used to notify the primary instance whenever a secondary instance had been
|
||||||
started (disabled by default). `timeout` specifies the maximum time in
|
started (disabled by default). `timeout` specifies the maximum time in
|
||||||
milliseconds to wait for blocking operations.
|
milliseconds to wait for blocking operations. Setting `userData` provides additional data that will isolate this instance from other instances that do not have the same (or any) user data set.
|
||||||
|
|
||||||
*__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it
|
*__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it
|
||||||
recognizes.*
|
recognizes.*
|
||||||
@@ -204,6 +215,22 @@ qint64 SingleApplication::primaryPid()
|
|||||||
|
|
||||||
Returns the process ID (PID) of the primary instance.
|
Returns the process ID (PID) of the primary instance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QString SingleApplication::primaryUser()
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the username the primary instance is running as.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
QString SingleApplication::currentUser()
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the username the current instance is running as.
|
||||||
|
|
||||||
### Signals
|
### Signals
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
#include "singleapplication.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.7.0)
|
||||||
|
|
||||||
|
project(basic LANGUAGES CXX)
|
||||||
|
|
||||||
|
# SingleApplication base class
|
||||||
|
set(QAPPLICATION_CLASS QCoreApplication)
|
||||||
|
add_subdirectory(../.. SingleApplication)
|
||||||
|
|
||||||
|
add_executable(basic main.cpp)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)
|
||||||
|
|
||||||
Regular → Executable
Regular → Executable
+2
@@ -5,5 +5,7 @@ int main(int argc, char *argv[])
|
|||||||
// Allow secondary instances
|
// Allow secondary instances
|
||||||
SingleApplication app( argc, argv );
|
SingleApplication app( argc, argv );
|
||||||
|
|
||||||
|
qWarning() << "Started a new instance";
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.7.0)
|
||||||
|
|
||||||
|
project(calculator LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
# SingleApplication base class
|
||||||
|
set(QAPPLICATION_CLASS QApplication)
|
||||||
|
add_subdirectory(../.. SingleApplication)
|
||||||
|
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core REQUIRED)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
button.h
|
||||||
|
calculator.h
|
||||||
|
button.cpp
|
||||||
|
calculator.cpp
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)
|
||||||
@@ -82,27 +82,27 @@ Calculator::Calculator(QWidget *parent)
|
|||||||
digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked()));
|
digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Button *pointButton = createButton(tr("."), SLOT(pointClicked()));
|
Button *pointButton = createButton(".", SLOT(pointClicked()));
|
||||||
Button *changeSignButton = createButton(tr("\302\261"), SLOT(changeSignClicked()));
|
Button *changeSignButton = createButton("\302\261", SLOT(changeSignClicked()));
|
||||||
|
|
||||||
Button *backspaceButton = createButton(tr("Backspace"), SLOT(backspaceClicked()));
|
Button *backspaceButton = createButton("Backspace", SLOT(backspaceClicked()));
|
||||||
Button *clearButton = createButton(tr("Clear"), SLOT(clear()));
|
Button *clearButton = createButton("Clear", SLOT(clear()));
|
||||||
Button *clearAllButton = createButton(tr("Clear All"), SLOT(clearAll()));
|
Button *clearAllButton = createButton("Clear All", SLOT(clearAll()));
|
||||||
|
|
||||||
Button *clearMemoryButton = createButton(tr("MC"), SLOT(clearMemory()));
|
Button *clearMemoryButton = createButton("MC", SLOT(clearMemory()));
|
||||||
Button *readMemoryButton = createButton(tr("MR"), SLOT(readMemory()));
|
Button *readMemoryButton = createButton("MR", SLOT(readMemory()));
|
||||||
Button *setMemoryButton = createButton(tr("MS"), SLOT(setMemory()));
|
Button *setMemoryButton = createButton("MS", SLOT(setMemory()));
|
||||||
Button *addToMemoryButton = createButton(tr("M+"), SLOT(addToMemory()));
|
Button *addToMemoryButton = createButton("M+", SLOT(addToMemory()));
|
||||||
|
|
||||||
Button *divisionButton = createButton(tr("\303\267"), SLOT(multiplicativeOperatorClicked()));
|
Button *divisionButton = createButton("\303\267", SLOT(multiplicativeOperatorClicked()));
|
||||||
Button *timesButton = createButton(tr("\303\227"), SLOT(multiplicativeOperatorClicked()));
|
Button *timesButton = createButton("\303\227", SLOT(multiplicativeOperatorClicked()));
|
||||||
Button *minusButton = createButton(tr("-"), SLOT(additiveOperatorClicked()));
|
Button *minusButton = createButton("-", SLOT(additiveOperatorClicked()));
|
||||||
Button *plusButton = createButton(tr("+"), SLOT(additiveOperatorClicked()));
|
Button *plusButton = createButton("+", SLOT(additiveOperatorClicked()));
|
||||||
|
|
||||||
Button *squareRootButton = createButton(tr("Sqrt"), SLOT(unaryOperatorClicked()));
|
Button *squareRootButton = createButton("Sqrt", SLOT(unaryOperatorClicked()));
|
||||||
Button *powerButton = createButton(tr("x\302\262"), SLOT(unaryOperatorClicked()));
|
Button *powerButton = createButton("x\302\262", SLOT(unaryOperatorClicked()));
|
||||||
Button *reciprocalButton = createButton(tr("1/x"), SLOT(unaryOperatorClicked()));
|
Button *reciprocalButton = createButton("1/x", SLOT(unaryOperatorClicked()));
|
||||||
Button *equalButton = createButton(tr("="), SLOT(equalClicked()));
|
Button *equalButton = createButton("=", SLOT(equalClicked()));
|
||||||
//! [4]
|
//! [4]
|
||||||
|
|
||||||
//! [5]
|
//! [5]
|
||||||
@@ -140,7 +140,7 @@ Calculator::Calculator(QWidget *parent)
|
|||||||
mainLayout->addWidget(equalButton, 5, 5);
|
mainLayout->addWidget(equalButton, 5, 5);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
setWindowTitle(tr("Calculator"));
|
setWindowTitle("Calculator");
|
||||||
}
|
}
|
||||||
//! [6]
|
//! [6]
|
||||||
|
|
||||||
@@ -169,15 +169,15 @@ void Calculator::unaryOperatorClicked()
|
|||||||
double operand = display->text().toDouble();
|
double operand = display->text().toDouble();
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
|
|
||||||
if (clickedOperator == tr("Sqrt")) {
|
if (clickedOperator == "Sqrt") {
|
||||||
if (operand < 0.0) {
|
if (operand < 0.0) {
|
||||||
abortOperation();
|
abortOperation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = std::sqrt(operand);
|
result = std::sqrt(operand);
|
||||||
} else if (clickedOperator == tr("x\302\262")) {
|
} else if (clickedOperator == "x\302\262") {
|
||||||
result = std::pow(operand, 2.0);
|
result = std::pow(operand, 2.0);
|
||||||
} else if (clickedOperator == tr("1/x")) {
|
} else if (clickedOperator == "1/x") {
|
||||||
if (operand == 0.0) {
|
if (operand == 0.0) {
|
||||||
abortOperation();
|
abortOperation();
|
||||||
return;
|
return;
|
||||||
@@ -287,7 +287,7 @@ void Calculator::pointClicked()
|
|||||||
if (waitingForOperand)
|
if (waitingForOperand)
|
||||||
display->setText("0");
|
display->setText("0");
|
||||||
if (!display->text().contains('.'))
|
if (!display->text().contains('.'))
|
||||||
display->setText(display->text() + tr("."));
|
display->setText(display->text() + ".");
|
||||||
waitingForOperand = false;
|
waitingForOperand = false;
|
||||||
}
|
}
|
||||||
//! [22]
|
//! [22]
|
||||||
@@ -299,7 +299,7 @@ void Calculator::changeSignClicked()
|
|||||||
double value = text.toDouble();
|
double value = text.toDouble();
|
||||||
|
|
||||||
if (value > 0.0) {
|
if (value > 0.0) {
|
||||||
text.prepend(tr("-"));
|
text.prepend("-");
|
||||||
} else if (value < 0.0) {
|
} else if (value < 0.0) {
|
||||||
text.remove(0, 1);
|
text.remove(0, 1);
|
||||||
}
|
}
|
||||||
@@ -383,20 +383,20 @@ Button *Calculator::createButton(const QString &text, const char *member)
|
|||||||
void Calculator::abortOperation()
|
void Calculator::abortOperation()
|
||||||
{
|
{
|
||||||
clearAll();
|
clearAll();
|
||||||
display->setText(tr("####"));
|
display->setText("####");
|
||||||
}
|
}
|
||||||
//! [36]
|
//! [36]
|
||||||
|
|
||||||
//! [38]
|
//! [38]
|
||||||
bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
|
bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
|
||||||
{
|
{
|
||||||
if (pendingOperator == tr("+")) {
|
if (pendingOperator == "+") {
|
||||||
sumSoFar += rightOperand;
|
sumSoFar += rightOperand;
|
||||||
} else if (pendingOperator == tr("-")) {
|
} else if (pendingOperator == "-") {
|
||||||
sumSoFar -= rightOperand;
|
sumSoFar -= rightOperand;
|
||||||
} else if (pendingOperator == tr("\303\227")) {
|
} else if (pendingOperator == "\303\227") {
|
||||||
factorSoFar *= rightOperand;
|
factorSoFar *= rightOperand;
|
||||||
} else if (pendingOperator == tr("\303\267")) {
|
} else if (pendingOperator == "\303\267") {
|
||||||
if (rightOperand == 0.0)
|
if (rightOperand == 0.0)
|
||||||
return false;
|
return false;
|
||||||
factorSoFar /= rightOperand;
|
factorSoFar /= rightOperand;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.7.0)
|
||||||
|
|
||||||
|
project(sending_arguments LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
# SingleApplication base class
|
||||||
|
set(QAPPLICATION_CLASS QCoreApplication)
|
||||||
|
add_subdirectory(../.. SingleApplication)
|
||||||
|
|
||||||
|
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS Core REQUIRED)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
main.cpp
|
||||||
|
messagereceiver.cpp
|
||||||
|
messagereceiver.h
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication)
|
||||||
Regular → Executable
+3
@@ -11,6 +11,9 @@ int main(int argc, char *argv[])
|
|||||||
// If this is a secondary instance
|
// If this is a secondary instance
|
||||||
if( app.isSecondary() ) {
|
if( app.isSecondary() ) {
|
||||||
app.sendMessage( app.arguments().join(' ').toUtf8() );
|
app.sendMessage( app.arguments().join(' ').toUtf8() );
|
||||||
|
qDebug() << "App already running.";
|
||||||
|
qDebug() << "Primary instance PID: " << app.primaryPid();
|
||||||
|
qDebug() << "Primary instance user: " << app.primaryUser();
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
|
|||||||
Regular → Executable
@@ -1,6 +1,6 @@
|
|||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) Itay Grudev 2015 - 2018
|
// Copyright (c) Itay Grudev 2015 - 2020
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -20,176 +20,255 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include <QtCore/QTime>
|
#include <QtCore/QElapsedTimer>
|
||||||
#include <QtCore/QThread>
|
|
||||||
#include <QtCore/QDateTime>
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtCore/QSharedMemory>
|
#include <QtCore/QSharedMemory>
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) // ### Qt 6: remove
|
|
||||||
#else
|
|
||||||
#if TODO_LIST
|
|
||||||
#pragma message("@TODO remove code for QT 5.10 or later")
|
|
||||||
#endif
|
|
||||||
#include <QRandomGenerator>
|
|
||||||
#endif
|
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
#include "singleapplication_p.h"
|
#include "singleapplication_p.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Constructor. Checks and fires up LocalServer or closes the program
|
* @brief Constructor. Checks and fires up LocalServer or closes the program
|
||||||
if another instance already exists
|
* if another instance already exists
|
||||||
@param argc
|
* @param argc
|
||||||
@param argv
|
* @param argv
|
||||||
@param {bool} allowSecondaryInstances
|
* @param allowSecondary Whether to enable secondary instance support
|
||||||
*/
|
* @param options Optional flags to toggle specific behaviour
|
||||||
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout )
|
* @param timeout Maximum time blocking functions are allowed during app load
|
||||||
: app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
|
*/
|
||||||
|
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout, const QString &userData )
|
||||||
|
: app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D( SingleApplication );
|
||||||
|
|
||||||
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
|
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
|
||||||
// On Android and iOS since the library is not supported fallback to
|
// On Android and iOS since the library is not supported fallback to
|
||||||
// standard QApplication behaviour by simply returning at this point.
|
// standard QApplication behaviour by simply returning at this point.
|
||||||
qWarning() << "SingleApplication is not supported on Android and iOS systems.";
|
qWarning() << "SingleApplication is not supported on Android and iOS systems.";
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Store the current mode of the program
|
// Store the current mode of the program
|
||||||
d->options = options;
|
d->options = options;
|
||||||
|
|
||||||
// Generating an application ID used for identifying the shared memory
|
// Add any unique user data
|
||||||
// block and QLocalServer
|
if ( ! userData.isEmpty() )
|
||||||
d->genBlockServerName();
|
d->addAppData( userData );
|
||||||
|
|
||||||
|
// Generating an application ID used for identifying the shared memory
|
||||||
|
// block and QLocalServer
|
||||||
|
d->genBlockServerName();
|
||||||
|
|
||||||
|
// To mitigate QSharedMemory issues with large amount of processes
|
||||||
|
// attempting to attach at the same time
|
||||||
|
SingleApplicationPrivate::randomSleep();
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
// By explicitly attaching it and then deleting it we make sure that the
|
// By explicitly attaching it and then deleting it we make sure that the
|
||||||
// memory is deleted even after the process has crashed on Unix.
|
// memory is deleted even after the process has crashed on Unix.
|
||||||
d->memory = new QSharedMemory( d->blockServerName );
|
d->memory = new QSharedMemory( d->blockServerName );
|
||||||
d->memory->attach();
|
d->memory->attach();
|
||||||
delete d->memory;
|
delete d->memory;
|
||||||
#endif
|
#endif
|
||||||
// Guarantee thread safe behaviour with a shared memory block.
|
// Guarantee thread safe behaviour with a shared memory block.
|
||||||
d->memory = new QSharedMemory( d->blockServerName );
|
d->memory = new QSharedMemory( d->blockServerName );
|
||||||
|
|
||||||
// Create a shared memory block
|
// Create a shared memory block
|
||||||
if( d->memory->create( sizeof( InstancesInfo ) ) ) {
|
if( d->memory->create( sizeof( InstancesInfo ) )){
|
||||||
// Initialize the shared memory block
|
// Initialize the shared memory block
|
||||||
d->memory->lock();
|
if( ! d->memory->lock() ){
|
||||||
d->initializeMemoryBlock();
|
qCritical() << "SingleApplication: Unable to lock memory block after create.";
|
||||||
d->memory->unlock();
|
abortSafely();
|
||||||
} else {
|
}
|
||||||
// Attempt to attach to the memory segment
|
d->initializeMemoryBlock();
|
||||||
if( ! d->memory->attach() ) {
|
} else {
|
||||||
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
|
if( d->memory->error() == QSharedMemory::AlreadyExists ){
|
||||||
qCritical() << d->memory->errorString();
|
// Attempt to attach to the memory segment
|
||||||
delete d;
|
if( ! d->memory->attach() ){
|
||||||
::exit( EXIT_FAILURE );
|
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
|
||||||
}
|
abortSafely();
|
||||||
}
|
}
|
||||||
|
if( ! d->memory->lock() ){
|
||||||
|
qCritical() << "SingleApplication: Unable to lock memory block after attach.";
|
||||||
|
abortSafely();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCritical() << "SingleApplication: Unable to create block.";
|
||||||
|
abortSafely();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( d->memory->data() );
|
auto *inst = static_cast<InstancesInfo*>( d->memory->data() );
|
||||||
QElapsedTimer time;
|
QElapsedTimer time;
|
||||||
time.start();
|
time.start();
|
||||||
|
|
||||||
// Make sure the shared memory block is initialised and in consistent state
|
// Make sure the shared memory block is initialised and in consistent state
|
||||||
while( true ) {
|
while( true ){
|
||||||
d->memory->lock();
|
// If the shared memory block's checksum is valid continue
|
||||||
|
if( d->blockChecksum() == inst->checksum ) break;
|
||||||
|
|
||||||
if( d->blockChecksum() == inst->checksum ) break;
|
// If more than 5s have elapsed, assume the primary instance crashed and
|
||||||
|
// assume it's position
|
||||||
|
if( time.elapsed() > 5000 ){
|
||||||
|
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
||||||
|
d->initializeMemoryBlock();
|
||||||
|
}
|
||||||
|
|
||||||
if( time.elapsed() > 5000 ) {
|
// Otherwise wait for a random period and try again. The random sleep here
|
||||||
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
// limits the probability of a collision between two racing apps and
|
||||||
d->initializeMemoryBlock();
|
// allows the app to initialise faster
|
||||||
}
|
if( ! d->memory->unlock() ){
|
||||||
|
qDebug() << "SingleApplication: Unable to unlock memory for random wait.";
|
||||||
|
qDebug() << d->memory->errorString();
|
||||||
|
}
|
||||||
|
SingleApplicationPrivate::randomSleep();
|
||||||
|
if( ! d->memory->lock() ){
|
||||||
|
qCritical() << "SingleApplication: Unable to lock memory after random wait.";
|
||||||
|
abortSafely();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
d->memory->unlock();
|
if( inst->primary == false ){
|
||||||
|
d->startPrimary();
|
||||||
|
if( ! d->memory->unlock() ){
|
||||||
|
qDebug() << "SingleApplication: Unable to unlock memory after primary start.";
|
||||||
|
qDebug() << d->memory->errorString();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Random sleep here limits the probability of a collision between two racing apps
|
// Check if another instance can be started
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) // ### Qt 6: remove
|
if( allowSecondary ){
|
||||||
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() );
|
d->startSecondary();
|
||||||
QThread::sleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 ) );
|
if( d->options & Mode::SecondaryNotification ){
|
||||||
#else
|
d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
|
||||||
#if TODO_LIST
|
}
|
||||||
#pragma message("@TODO remove code for QT 5.10 or later")
|
if( ! d->memory->unlock() ){
|
||||||
#endif
|
qDebug() << "SingleApplication: Unable to unlock memory after secondary start.";
|
||||||
quint32 value = QRandomGenerator::global()->generate();
|
qDebug() << d->memory->errorString();
|
||||||
QThread::sleep(8 + static_cast<unsigned long>(value / RAND_MAX * 10));
|
}
|
||||||
#endif
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( inst->primary == false) {
|
if( ! d->memory->unlock() ){
|
||||||
d->startPrimary();
|
qDebug() << "SingleApplication: Unable to unlock memory at end of execution.";
|
||||||
d->memory->unlock();
|
qDebug() << d->memory->errorString();
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check if another instance can be started
|
d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
|
||||||
if( allowSecondary ) {
|
|
||||||
inst->secondary += 1;
|
|
||||||
inst->checksum = d->blockChecksum();
|
|
||||||
d->instanceNumber = inst->secondary;
|
|
||||||
d->startSecondary();
|
|
||||||
if( d->options & Mode::SecondaryNotification ) {
|
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
|
|
||||||
}
|
|
||||||
d->memory->unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->memory->unlock();
|
delete d;
|
||||||
|
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
|
::exit( EXIT_SUCCESS );
|
||||||
|
}
|
||||||
|
|
||||||
delete d;
|
SingleApplication::~SingleApplication()
|
||||||
|
{
|
||||||
::exit( EXIT_SUCCESS );
|
Q_D( SingleApplication );
|
||||||
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Destructor
|
* Checks if the current application instance is primary.
|
||||||
*/
|
* @return Returns true if the instance is primary, false otherwise.
|
||||||
SingleApplication::~SingleApplication()
|
*/
|
||||||
|
bool SingleApplication::isPrimary() const
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D( const SingleApplication );
|
||||||
delete d;
|
return d->server != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplication::isPrimary()
|
/**
|
||||||
|
* Checks if the current application instance is secondary.
|
||||||
|
* @return Returns true if the instance is secondary, false otherwise.
|
||||||
|
*/
|
||||||
|
bool SingleApplication::isSecondary() const
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D( const SingleApplication );
|
||||||
return d->server != nullptr;
|
return d->server == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplication::isSecondary()
|
/**
|
||||||
|
* Allows you to identify an instance by returning unique consecutive instance
|
||||||
|
* ids. It is reset when the first (primary) instance of your app starts and
|
||||||
|
* only incremented afterwards.
|
||||||
|
* @return Returns a unique instance id.
|
||||||
|
*/
|
||||||
|
quint32 SingleApplication::instanceId() const
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D( const SingleApplication );
|
||||||
return d->server == nullptr;
|
return d->instanceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 SingleApplication::instanceId()
|
/**
|
||||||
|
* Returns the OS PID (Process Identifier) of the process running the primary
|
||||||
|
* instance. Especially useful when SingleApplication is coupled with OS.
|
||||||
|
* specific APIs.
|
||||||
|
* @return Returns the primary instance PID.
|
||||||
|
*/
|
||||||
|
qint64 SingleApplication::primaryPid() const
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D( const SingleApplication );
|
||||||
return d->instanceNumber;
|
return d->primaryPid();
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 SingleApplication::primaryPid()
|
/**
|
||||||
|
* Returns the username the primary instance is running as.
|
||||||
|
* @return Returns the username the primary instance is running as.
|
||||||
|
*/
|
||||||
|
QString SingleApplication::primaryUser() const
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
Q_D( const SingleApplication );
|
||||||
return d->primaryPid();
|
return d->primaryUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplication::sendMessage( QByteArray message, int timeout )
|
/**
|
||||||
|
* Returns the username the current instance is running as.
|
||||||
|
* @return Returns the username the current instance is running as.
|
||||||
|
*/
|
||||||
|
QString SingleApplication::currentUser() const
|
||||||
{
|
{
|
||||||
Q_D(SingleApplication);
|
return SingleApplicationPrivate::getUsername();
|
||||||
|
}
|
||||||
// Nobody to connect to
|
|
||||||
if( isPrimary() ) return false;
|
/**
|
||||||
|
* Sends message to the Primary Instance.
|
||||||
// Make sure the socket is connected
|
* @param message The message to send.
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect );
|
* @param timeout the maximum timeout in milliseconds for blocking functions.
|
||||||
|
* @return true if the message was sent successfuly, false otherwise.
|
||||||
d->socket->write( message );
|
*/
|
||||||
bool dataWritten = d->socket->waitForBytesWritten( timeout );
|
bool SingleApplication::sendMessage( const QByteArray &message, int timeout )
|
||||||
d->socket->flush();
|
{
|
||||||
return dataWritten;
|
Q_D( SingleApplication );
|
||||||
|
|
||||||
|
// Nobody to connect to
|
||||||
|
if( isPrimary() ) return false;
|
||||||
|
|
||||||
|
// Make sure the socket is connected
|
||||||
|
if( ! d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
d->socket->write( message );
|
||||||
|
bool dataWritten = d->socket->waitForBytesWritten( timeout );
|
||||||
|
d->socket->flush();
|
||||||
|
return dataWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up the shared memory block and exits with a failure.
|
||||||
|
* This function halts program execution.
|
||||||
|
*/
|
||||||
|
void SingleApplication::abortSafely()
|
||||||
|
{
|
||||||
|
Q_D( SingleApplication );
|
||||||
|
|
||||||
|
qCritical() << "SingleApplication: " << d->memory->error() << d->memory->errorString();
|
||||||
|
delete d;
|
||||||
|
::exit( EXIT_FAILURE );
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SingleApplication::userData() const
|
||||||
|
{
|
||||||
|
Q_D( const SingleApplication );
|
||||||
|
return d->appData();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
#include <QtCore/QtGlobal>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QtNetwork/QLocalSocket>
|
||||||
#include <QElapsedTimer>
|
|
||||||
|
|
||||||
#ifndef QAPPLICATION_CLASS
|
#ifndef QAPPLICATION_CLASS
|
||||||
#define QAPPLICATION_CLASS QCoreApplication
|
#define QAPPLICATION_CLASS QCoreApplication
|
||||||
@@ -36,99 +35,118 @@
|
|||||||
class SingleApplicationPrivate;
|
class SingleApplicationPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief The SingleApplication class handles multiple instances of the same
|
* @brief The SingleApplication class handles multiple instances of the same
|
||||||
Application
|
* Application
|
||||||
@see QCoreApplication
|
* @see QCoreApplication
|
||||||
*/
|
*/
|
||||||
class SingleApplication : public QAPPLICATION_CLASS
|
class SingleApplication : public QAPPLICATION_CLASS
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
typedef QAPPLICATION_CLASS app_t;
|
using app_t = QAPPLICATION_CLASS;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@brief Mode of operation of SingleApplication.
|
* @brief Mode of operation of SingleApplication.
|
||||||
Whether the block should be user-wide or system-wide and whether the
|
* Whether the block should be user-wide or system-wide and whether the
|
||||||
primary instance should be notified when a secondary instance had been
|
* primary instance should be notified when a secondary instance had been
|
||||||
started.
|
* started.
|
||||||
@note Operating system can restrict the shared memory blocks to the same
|
* @note Operating system can restrict the shared memory blocks to the same
|
||||||
user, in which case the User/System modes will have no effect and the
|
* user, in which case the User/System modes will have no effect and the
|
||||||
block will be user wide.
|
* block will be user wide.
|
||||||
@enum
|
* @enum
|
||||||
*/
|
*/
|
||||||
enum Mode {
|
enum Mode {
|
||||||
User = 1 << 0,
|
User = 1 << 0,
|
||||||
System = 1 << 1,
|
System = 1 << 1,
|
||||||
SecondaryNotification = 1 << 2,
|
SecondaryNotification = 1 << 2,
|
||||||
ExcludeAppVersion = 1 << 3,
|
ExcludeAppVersion = 1 << 3,
|
||||||
ExcludeAppPath = 1 << 4
|
ExcludeAppPath = 1 << 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Mode)
|
Q_DECLARE_FLAGS(Options, Mode)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Intitializes a SingleApplication instance with argc command line
|
* @brief Intitializes a SingleApplication instance with argc command line
|
||||||
arguments in argv
|
* arguments in argv
|
||||||
@arg {int &} argc - Number of arguments in argv
|
* @arg {int &} argc - Number of arguments in argv
|
||||||
@arg {const char *[]} argv - Supplied command line arguments
|
* @arg {const char *[]} argv - Supplied command line arguments
|
||||||
@arg {bool} allowSecondary - Whether to start the instance as secondary
|
* @arg {bool} allowSecondary - Whether to start the instance as secondary
|
||||||
if there is already a primary instance.
|
* if there is already a primary instance.
|
||||||
@arg {Mode} mode - Whether for the SingleApplication block to be applied
|
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
|
||||||
User wide or System wide.
|
* User wide or System wide.
|
||||||
@arg {int} timeout - Timeout to wait in milliseconds.
|
* @arg {int} timeout - Timeout to wait in milliseconds.
|
||||||
@note argc and argv may be changed as Qt removes arguments that it
|
* @note argc and argv may be changed as Qt removes arguments that it
|
||||||
recognizes
|
* recognizes
|
||||||
@note Mode::SecondaryNotification only works if set on both the primary
|
* @note Mode::SecondaryNotification only works if set on both the primary
|
||||||
instance and the secondary instance.
|
* instance and the secondary instance.
|
||||||
@note The timeout is just a hint for the maximum time of blocking
|
* @note The timeout is just a hint for the maximum time of blocking
|
||||||
operations. It does not guarantee that the SingleApplication
|
* operations. It does not guarantee that the SingleApplication
|
||||||
initialisation will be completed in given time, though is a good hint.
|
* initialisation will be completed in given time, though is a good hint.
|
||||||
Usually 4*timeout would be the worst case (fail) scenario.
|
* Usually 4*timeout would be the worst case (fail) scenario.
|
||||||
@see See the corresponding QAPPLICATION_CLASS constructor for reference
|
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
|
||||||
*/
|
*/
|
||||||
explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
|
explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000, const QString &userData = {} );
|
||||||
~SingleApplication();
|
~SingleApplication() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Returns if the instance is the primary instance
|
* @brief Returns if the instance is the primary instance
|
||||||
@returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isPrimary();
|
bool isPrimary() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Returns if the instance is a secondary instance
|
* @brief Returns if the instance is a secondary instance
|
||||||
@returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isSecondary();
|
bool isSecondary() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Returns a unique identifier for the current instance
|
* @brief Returns a unique identifier for the current instance
|
||||||
@returns {qint32}
|
* @returns {qint32}
|
||||||
*/
|
*/
|
||||||
quint32 instanceId();
|
quint32 instanceId() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Returns the process ID (PID) of the primary instance
|
* @brief Returns the process ID (PID) of the primary instance
|
||||||
@returns {qint64}
|
* @returns {qint64}
|
||||||
*/
|
*/
|
||||||
qint64 primaryPid();
|
qint64 primaryPid() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Sends a message to the primary instance. Returns true on success.
|
* @brief Returns the username of the user running the primary instance
|
||||||
@param {int} timeout - Timeout for connecting
|
* @returns {QString}
|
||||||
@returns {bool}
|
*/
|
||||||
@note sendMessage() will return false if invoked from the primary
|
QString primaryUser() const;
|
||||||
instance.
|
|
||||||
*/
|
/**
|
||||||
bool sendMessage( QByteArray message, int timeout = 100 );
|
* @brief Returns the username of the current user
|
||||||
|
* @returns {QString}
|
||||||
Q_SIGNALS:
|
*/
|
||||||
void instanceStarted();
|
QString currentUser() const;
|
||||||
void receivedMessage( quint32 instanceId, QByteArray message );
|
|
||||||
|
/**
|
||||||
private:
|
* @brief Sends a message to the primary instance. Returns true on success.
|
||||||
SingleApplicationPrivate *d_ptr;
|
* @param {int} timeout - Timeout for connecting
|
||||||
Q_DECLARE_PRIVATE(SingleApplication)
|
* @returns {bool}
|
||||||
|
* @note sendMessage() will return false if invoked from the primary
|
||||||
|
* instance.
|
||||||
|
*/
|
||||||
|
bool sendMessage( const QByteArray &message, int timeout = 100 );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the set user data.
|
||||||
|
* @returns {QStringList}
|
||||||
|
*/
|
||||||
|
QStringList userData() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void instanceStarted();
|
||||||
|
void receivedMessage( quint32 instanceId, QByteArray message );
|
||||||
|
|
||||||
|
private:
|
||||||
|
SingleApplicationPrivate *d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(SingleApplication)
|
||||||
|
void abortSafely();
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
QT += core network
|
QT += core network
|
||||||
CONFIG += c++17
|
CONFIG += c++11
|
||||||
|
|
||||||
HEADERS += $$PWD/singleapplication.h \
|
HEADERS += $$PWD/SingleApplication \
|
||||||
|
$$PWD/singleapplication.h \
|
||||||
$$PWD/singleapplication_p.h
|
$$PWD/singleapplication_p.h
|
||||||
SOURCES += $$PWD/singleapplication.cpp \
|
SOURCES += $$PWD/singleapplication.cpp \
|
||||||
$$PWD/singleapplication_p.cpp
|
$$PWD/singleapplication_p.cpp
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) Itay Grudev 2015 - 2018
|
// Copyright (c) Itay Grudev 2015 - 2020
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -33,412 +33,454 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
|
#include <QtCore/QThread>
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtCore/QDataStream>
|
#include <QtCore/QDataStream>
|
||||||
|
#include <QtCore/QElapsedTimer>
|
||||||
#include <QtCore/QCryptographicHash>
|
#include <QtCore/QCryptographicHash>
|
||||||
#include <QtNetwork/QLocalServer>
|
#include <QtNetwork/QLocalServer>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QtNetwork/QLocalSocket>
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||||
|
#include <QtCore/QRandomGenerator>
|
||||||
|
#else
|
||||||
|
#include <QtCore/QDateTime>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
#include "singleapplication_p.h"
|
#include "singleapplication_p.h"
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
#ifndef NOMINMAX
|
||||||
#include <lmcons.h>
|
#define NOMINMAX 1
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#include <lmcons.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr )
|
SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr )
|
||||||
: q_ptr( q_ptr )
|
: q_ptr( q_ptr )
|
||||||
{
|
{
|
||||||
server = nullptr;
|
server = nullptr;
|
||||||
socket = nullptr;
|
socket = nullptr;
|
||||||
memory = nullptr;
|
memory = nullptr;
|
||||||
instanceNumber = -1;
|
instanceNumber = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleApplicationPrivate::~SingleApplicationPrivate()
|
SingleApplicationPrivate::~SingleApplicationPrivate()
|
||||||
{
|
{
|
||||||
if( socket != nullptr ) {
|
if( socket != nullptr ){
|
||||||
socket->close();
|
socket->close();
|
||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory->lock();
|
if( memory != nullptr ){
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
memory->lock();
|
||||||
if( server != nullptr ) {
|
auto *inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
server->close();
|
if( server != nullptr ){
|
||||||
delete server;
|
server->close();
|
||||||
inst->primary = false;
|
delete server;
|
||||||
inst->primaryPid = -1;
|
inst->primary = false;
|
||||||
inst->checksum = blockChecksum();
|
inst->primaryPid = -1;
|
||||||
}
|
inst->primaryUser[0] = '\0';
|
||||||
memory->unlock();
|
inst->checksum = blockChecksum();
|
||||||
|
}
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
delete memory;
|
delete memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SingleApplicationPrivate::getUsername()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
wchar_t username[UNLEN + 1];
|
||||||
|
// Specifies size of the buffer on input
|
||||||
|
DWORD usernameLength = UNLEN + 1;
|
||||||
|
if( GetUserNameW( username, &usernameLength ) )
|
||||||
|
return QString::fromWCharArray( username );
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||||
|
return QString::fromLocal8Bit( qgetenv( "USERNAME" ) );
|
||||||
|
#else
|
||||||
|
return qEnvironmentVariable( "USERNAME" );
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
QString username;
|
||||||
|
uid_t uid = geteuid();
|
||||||
|
struct passwd *pw = getpwuid( uid );
|
||||||
|
if( pw )
|
||||||
|
username = QString::fromLocal8Bit( pw->pw_name );
|
||||||
|
if ( username.isEmpty() ){
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||||
|
username = QString::fromLocal8Bit( qgetenv( "USER" ) );
|
||||||
|
#else
|
||||||
|
username = qEnvironmentVariable( "USER" );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::genBlockServerName()
|
void SingleApplicationPrivate::genBlockServerName()
|
||||||
{
|
{
|
||||||
QCryptographicHash appData( QCryptographicHash::Sha256 );
|
QCryptographicHash appData( QCryptographicHash::Sha256 );
|
||||||
appData.addData( "SingleApplication", 17 );
|
appData.addData( "SingleApplication", 17 );
|
||||||
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
|
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
|
||||||
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
|
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
|
||||||
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
|
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
|
||||||
|
|
||||||
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ) {
|
if ( ! appDataList.isEmpty() )
|
||||||
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
|
appData.addData( appDataList.join( "" ).toUtf8() );
|
||||||
}
|
|
||||||
|
|
||||||
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ) {
|
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){
|
||||||
|
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
|
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
|
||||||
#else
|
#else
|
||||||
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
|
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// User level block requires a user specific data in the hash
|
// User level block requires a user specific data in the hash
|
||||||
if( options & SingleApplication::Mode::User ) {
|
if( options & SingleApplication::Mode::User ){
|
||||||
#ifdef Q_OS_WIN
|
appData.addData( getUsername().toUtf8() );
|
||||||
wchar_t username [ UNLEN + 1 ];
|
}
|
||||||
// Specifies size of the buffer on input
|
|
||||||
DWORD usernameLength = UNLEN + 1;
|
|
||||||
if( GetUserNameW( username, &usernameLength ) ) {
|
|
||||||
appData.addData( QString::fromWCharArray(username).toUtf8() );
|
|
||||||
} else {
|
|
||||||
appData.addData( qgetenv("USERNAME") );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_UNIX
|
|
||||||
QByteArray username;
|
|
||||||
uid_t uid = geteuid();
|
|
||||||
struct passwd *pw = getpwuid(uid);
|
|
||||||
if( pw ) {
|
|
||||||
username = pw->pw_name;
|
|
||||||
}
|
|
||||||
if( username.isEmpty() ) {
|
|
||||||
username = qgetenv("USER");
|
|
||||||
}
|
|
||||||
appData.addData(username);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
|
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
|
||||||
// server naming requirements.
|
// server naming requirements.
|
||||||
blockServerName = appData.result().toBase64().replace("/", "_");
|
blockServerName = appData.result().toBase64().replace("/", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::initializeMemoryBlock()
|
void SingleApplicationPrivate::initializeMemoryBlock() const
|
||||||
{
|
{
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
|
auto *inst = static_cast<InstancesInfo*>( memory->data() );
|
||||||
inst->primary = false;
|
inst->primary = false;
|
||||||
inst->secondary = 0;
|
inst->secondary = 0;
|
||||||
inst->primaryPid = -1;
|
inst->primaryPid = -1;
|
||||||
inst->checksum = blockChecksum();
|
inst->primaryUser[0] = '\0';
|
||||||
|
inst->checksum = blockChecksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::startPrimary()
|
void SingleApplicationPrivate::startPrimary()
|
||||||
{
|
{
|
||||||
Q_Q(SingleApplication);
|
// Reset the number of connections
|
||||||
|
auto *inst = static_cast <InstancesInfo*>( memory->data() );
|
||||||
|
|
||||||
// Successful creation means that no main process exists
|
inst->primary = true;
|
||||||
// So we start a QLocalServer to listen for connections
|
inst->primaryPid = QCoreApplication::applicationPid();
|
||||||
QLocalServer::removeServer( blockServerName );
|
qstrncpy( inst->primaryUser, getUsername().toUtf8().data(), sizeof(inst->primaryUser) );
|
||||||
server = new QLocalServer();
|
inst->checksum = blockChecksum();
|
||||||
|
instanceNumber = 0;
|
||||||
|
// Successful creation means that no main process exists
|
||||||
|
// So we start a QLocalServer to listen for connections
|
||||||
|
QLocalServer::removeServer( blockServerName );
|
||||||
|
server = new QLocalServer();
|
||||||
|
|
||||||
// Restrict access to the socket according to the
|
// Restrict access to the socket according to the
|
||||||
// SingleApplication::Mode::User flag on User level or no restrictions
|
// SingleApplication::Mode::User flag on User level or no restrictions
|
||||||
if( options & SingleApplication::Mode::User ) {
|
if( options & SingleApplication::Mode::User ){
|
||||||
server->setSocketOptions( QLocalServer::UserAccessOption );
|
server->setSocketOptions( QLocalServer::UserAccessOption );
|
||||||
} else {
|
} else {
|
||||||
server->setSocketOptions( QLocalServer::WorldAccessOption );
|
server->setSocketOptions( QLocalServer::WorldAccessOption );
|
||||||
}
|
}
|
||||||
|
|
||||||
server->listen( blockServerName );
|
server->listen( blockServerName );
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
server,
|
server,
|
||||||
&QLocalServer::newConnection,
|
&QLocalServer::newConnection,
|
||||||
this,
|
this,
|
||||||
&SingleApplicationPrivate::slotConnectionEstablished
|
&SingleApplicationPrivate::slotConnectionEstablished
|
||||||
);
|
);
|
||||||
|
|
||||||
// Reset the number of connections
|
|
||||||
InstancesInfo* inst = static_cast <InstancesInfo*>( memory->data() );
|
|
||||||
|
|
||||||
inst->primary = true;
|
|
||||||
inst->primaryPid = q->applicationPid();
|
|
||||||
inst->checksum = blockChecksum();
|
|
||||||
|
|
||||||
instanceNumber = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::startSecondary()
|
void SingleApplicationPrivate::startSecondary()
|
||||||
{
|
{
|
||||||
|
auto *inst = static_cast <InstancesInfo*>( memory->data() );
|
||||||
|
|
||||||
|
inst->secondary += 1;
|
||||||
|
inst->checksum = blockChecksum();
|
||||||
|
instanceNumber = inst->secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
|
bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
|
||||||
{
|
{
|
||||||
// Connect to the Local Server of the Primary Instance if not already
|
QElapsedTimer time;
|
||||||
// connected.
|
time.start();
|
||||||
if( socket == nullptr ) {
|
|
||||||
socket = new QLocalSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If already connected - we are done;
|
// Connect to the Local Server of the Primary Instance if not already
|
||||||
if( socket->state() == QLocalSocket::ConnectedState )
|
// connected.
|
||||||
return;
|
if( socket == nullptr ){
|
||||||
|
socket = new QLocalSocket();
|
||||||
|
}
|
||||||
|
|
||||||
// If not connect
|
if( socket->state() == QLocalSocket::ConnectedState ) return true;
|
||||||
if( socket->state() == QLocalSocket::UnconnectedState ||
|
|
||||||
socket->state() == QLocalSocket::ClosingState ) {
|
|
||||||
socket->connectToServer( blockServerName );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for being connected
|
if( socket->state() != QLocalSocket::ConnectedState ){
|
||||||
if( socket->state() == QLocalSocket::ConnectingState ) {
|
|
||||||
socket->waitForConnected( msecs );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialisation message according to the SingleApplication protocol
|
while( true ){
|
||||||
if( socket->state() == QLocalSocket::ConnectedState ) {
|
randomSleep();
|
||||||
// Notify the parent that a new instance had been started;
|
|
||||||
QByteArray initMsg;
|
if( socket->state() != QLocalSocket::ConnectingState )
|
||||||
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
socket->connectToServer( blockServerName );
|
||||||
|
|
||||||
|
if( socket->state() == QLocalSocket::ConnectingState ){
|
||||||
|
socket->waitForConnected( static_cast<int>(msecs - time.elapsed()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// If connected break out of the loop
|
||||||
|
if( socket->state() == QLocalSocket::ConnectedState ) break;
|
||||||
|
|
||||||
|
// If elapsed time since start is longer than the method timeout return
|
||||||
|
if( time.elapsed() >= msecs ) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisation message according to the SingleApplication protocol
|
||||||
|
QByteArray initMsg;
|
||||||
|
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||||
writeStream.setVersion(QDataStream::Qt_5_6);
|
writeStream.setVersion(QDataStream::Qt_5_6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
writeStream << blockServerName.toLatin1();
|
writeStream << blockServerName.toLatin1();
|
||||||
writeStream << static_cast<quint8>(connectionType);
|
writeStream << static_cast<quint8>(connectionType);
|
||||||
writeStream << instanceNumber;
|
writeStream << instanceNumber;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
quint16 checksum = qChecksum(QByteArray(initMsg, static_cast<quint32>(initMsg.length())));
|
||||||
quint16 checksum =
|
|
||||||
qChecksum(
|
|
||||||
initMsg.constData(),
|
|
||||||
static_cast<quint32>(initMsg.length()));
|
|
||||||
#else
|
#else
|
||||||
#if TODO_LIST
|
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
||||||
#pragma message("@TODO remove code for QT 6 or later")
|
|
||||||
#endif
|
#endif
|
||||||
quint16 checksum =
|
writeStream << checksum;
|
||||||
qChecksum(
|
|
||||||
QByteArrayView(
|
|
||||||
initMsg.constData(),
|
|
||||||
static_cast<quint32>(initMsg.length())));
|
|
||||||
#endif
|
|
||||||
writeStream << checksum;
|
|
||||||
|
|
||||||
// The header indicates the message length that follows
|
// The header indicates the message length that follows
|
||||||
QByteArray header;
|
QByteArray header;
|
||||||
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||||
headerStream.setVersion(QDataStream::Qt_5_6);
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
#endif
|
#endif
|
||||||
headerStream << static_cast <quint64>( initMsg.length() );
|
headerStream << static_cast <quint64>( initMsg.length() );
|
||||||
|
|
||||||
socket->write( header );
|
socket->write( header );
|
||||||
socket->write( initMsg );
|
socket->write( initMsg );
|
||||||
socket->flush();
|
bool result = socket->waitForBytesWritten( static_cast<int>(msecs - time.elapsed()) );
|
||||||
socket->waitForBytesWritten( msecs );
|
socket->flush();
|
||||||
}
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 SingleApplicationPrivate::blockChecksum()
|
quint16 SingleApplicationPrivate::blockChecksum() const
|
||||||
{
|
{
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
return qChecksum(
|
quint16 checksum = qChecksum(QByteArray(static_cast<const char*>(memory->constData()), offsetof(InstancesInfo, checksum)));
|
||||||
static_cast <const char *>( memory->data() ),
|
|
||||||
offsetof( InstancesInfo, checksum )
|
|
||||||
);
|
|
||||||
#else
|
#else
|
||||||
#if TODO_LIST
|
quint16 checksum = qChecksum(static_cast<const char*>(memory->constData()), offsetof(InstancesInfo, checksum));
|
||||||
#pragma message("@TODO remove code for QT 6 or later")
|
|
||||||
#endif
|
|
||||||
return qChecksum(
|
|
||||||
QByteArrayView(
|
|
||||||
static_cast <const char *>( memory->data() ),
|
|
||||||
offsetof( InstancesInfo, checksum )));
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
return checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 SingleApplicationPrivate::primaryPid()
|
qint64 SingleApplicationPrivate::primaryPid() const
|
||||||
{
|
{
|
||||||
qint64 pid;
|
qint64 pid;
|
||||||
|
|
||||||
memory->lock();
|
memory->lock();
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
|
auto *inst = static_cast<InstancesInfo*>( memory->data() );
|
||||||
pid = inst->primaryPid;
|
pid = inst->primaryPid;
|
||||||
memory->unlock();
|
memory->unlock();
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SingleApplicationPrivate::primaryUser() const
|
||||||
|
{
|
||||||
|
QByteArray username;
|
||||||
|
|
||||||
|
memory->lock();
|
||||||
|
auto *inst = static_cast<InstancesInfo*>( memory->data() );
|
||||||
|
username = inst->primaryUser;
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
|
return QString::fromUtf8( username );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Executed when a connection has been made to the LocalServer
|
* @brief Executed when a connection has been made to the LocalServer
|
||||||
*/
|
*/
|
||||||
void SingleApplicationPrivate::slotConnectionEstablished()
|
void SingleApplicationPrivate::slotConnectionEstablished()
|
||||||
{
|
{
|
||||||
QLocalSocket *nextConnSocket = server->nextPendingConnection();
|
QLocalSocket *nextConnSocket = server->nextPendingConnection();
|
||||||
connectionMap.insert(nextConnSocket, ConnectionInfo());
|
connectionMap.insert(nextConnSocket, ConnectionInfo());
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
|
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
|
||||||
[nextConnSocket, this]() {
|
[nextConnSocket, this](){
|
||||||
auto &info = connectionMap[nextConnSocket];
|
auto &info = connectionMap[nextConnSocket];
|
||||||
Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
|
Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
|
QObject::connect(nextConnSocket, &QLocalSocket::disconnected, nextConnSocket, &QLocalSocket::deleteLater);
|
||||||
[nextConnSocket, this](){
|
|
||||||
connectionMap.remove(nextConnSocket);
|
|
||||||
nextConnSocket->deleteLater();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
QObject::connect(nextConnSocket, &QLocalSocket::destroyed,
|
||||||
[nextConnSocket, this]() {
|
[nextConnSocket, this](){
|
||||||
auto &info = connectionMap[nextConnSocket];
|
connectionMap.remove(nextConnSocket);
|
||||||
switch(info.stage) {
|
}
|
||||||
case StageHeader:
|
);
|
||||||
readInitMessageHeader(nextConnSocket);
|
|
||||||
break;
|
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
||||||
case StageBody:
|
[nextConnSocket, this](){
|
||||||
readInitMessageBody(nextConnSocket);
|
auto &info = connectionMap[nextConnSocket];
|
||||||
break;
|
switch(info.stage){
|
||||||
case StageConnected:
|
case StageHeader:
|
||||||
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
|
readInitMessageHeader(nextConnSocket);
|
||||||
break;
|
break;
|
||||||
default:
|
case StageBody:
|
||||||
break;
|
readInitMessageBody(nextConnSocket);
|
||||||
};
|
break;
|
||||||
}
|
case StageConnected:
|
||||||
);
|
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
|
void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
|
||||||
{
|
{
|
||||||
if (!connectionMap.contains( sock )) {
|
if (!connectionMap.contains( sock )){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ) {
|
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream headerStream( sock );
|
QDataStream headerStream( sock );
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||||
headerStream.setVersion( QDataStream::Qt_5_6 );
|
headerStream.setVersion( QDataStream::Qt_5_6 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Read the header to know the message length
|
// Read the header to know the message length
|
||||||
quint64 msgLen = 0;
|
quint64 msgLen = 0;
|
||||||
headerStream >> msgLen;
|
headerStream >> msgLen;
|
||||||
ConnectionInfo &info = connectionMap[sock];
|
ConnectionInfo &info = connectionMap[sock];
|
||||||
info.stage = StageBody;
|
info.stage = StageBody;
|
||||||
info.msgLen = msgLen;
|
info.msgLen = msgLen;
|
||||||
|
|
||||||
if ( sock->bytesAvailable() >= (qint64) msgLen ) {
|
if ( sock->bytesAvailable() >= (qint64) msgLen ){
|
||||||
readInitMessageBody( sock );
|
readInitMessageBody( sock );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
|
void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
|
||||||
{
|
{
|
||||||
Q_Q(SingleApplication);
|
Q_Q(SingleApplication);
|
||||||
|
|
||||||
if (!connectionMap.contains( sock )) {
|
if (!connectionMap.contains( sock )){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionInfo &info = connectionMap[sock];
|
ConnectionInfo &info = connectionMap[sock];
|
||||||
if( sock->bytesAvailable() < ( qint64 )info.msgLen ) {
|
if( sock->bytesAvailable() < ( qint64 )info.msgLen ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the message body
|
// Read the message body
|
||||||
QByteArray msgBytes = sock->read(info.msgLen);
|
QByteArray msgBytes = sock->read(info.msgLen);
|
||||||
QDataStream readStream(msgBytes);
|
QDataStream readStream(msgBytes);
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||||
readStream.setVersion( QDataStream::Qt_5_6 );
|
readStream.setVersion( QDataStream::Qt_5_6 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// server name
|
// server name
|
||||||
QByteArray latin1Name;
|
QByteArray latin1Name;
|
||||||
readStream >> latin1Name;
|
readStream >> latin1Name;
|
||||||
|
|
||||||
// connection type
|
// connection type
|
||||||
ConnectionType connectionType = InvalidConnection;
|
ConnectionType connectionType = InvalidConnection;
|
||||||
quint8 connTypeVal = InvalidConnection;
|
quint8 connTypeVal = InvalidConnection;
|
||||||
readStream >> connTypeVal;
|
readStream >> connTypeVal;
|
||||||
connectionType = static_cast <ConnectionType>( connTypeVal );
|
connectionType = static_cast <ConnectionType>( connTypeVal );
|
||||||
|
|
||||||
// instance id
|
// instance id
|
||||||
quint32 instanceId = 0;
|
quint32 instanceId = 0;
|
||||||
readStream >> instanceId;
|
readStream >> instanceId;
|
||||||
|
|
||||||
// checksum
|
// checksum
|
||||||
quint16 msgChecksum = 0;
|
quint16 msgChecksum = 0;
|
||||||
readStream >> msgChecksum;
|
readStream >> msgChecksum;
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
const quint16 actualChecksum =
|
const quint16 actualChecksum = qChecksum(QByteArray(msgBytes, static_cast<quint32>(msgBytes.length() - sizeof(quint16))));
|
||||||
qChecksum(
|
|
||||||
msgBytes.constData(),
|
|
||||||
static_cast<quint32>( msgBytes.length() - sizeof( quint16 ) ) );
|
|
||||||
#else
|
#else
|
||||||
#if TODO_LIST
|
const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length() - sizeof(quint16)));
|
||||||
#pragma message("@TODO remove code for QT 6 or later")
|
|
||||||
#endif
|
#endif
|
||||||
const quint16 actualChecksum =
|
|
||||||
qChecksum(
|
|
||||||
QByteArrayView(
|
|
||||||
msgBytes.constData(),
|
|
||||||
static_cast<quint32>(msgBytes.length() - sizeof(quint16))));
|
|
||||||
#endif
|
|
||||||
bool isValid = readStream.status() == QDataStream::Ok &&
|
|
||||||
QLatin1String(latin1Name) == blockServerName &&
|
|
||||||
msgChecksum == actualChecksum;
|
|
||||||
|
|
||||||
if( !isValid ) {
|
bool isValid = readStream.status() == QDataStream::Ok &&
|
||||||
sock->close();
|
QLatin1String(latin1Name) == blockServerName &&
|
||||||
return;
|
msgChecksum == actualChecksum;
|
||||||
}
|
|
||||||
|
|
||||||
info.instanceId = instanceId;
|
if( !isValid ){
|
||||||
info.stage = StageConnected;
|
sock->close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( connectionType == NewInstance ||
|
info.instanceId = instanceId;
|
||||||
( connectionType == SecondaryInstance &&
|
info.stage = StageConnected;
|
||||||
options & SingleApplication::Mode::SecondaryNotification ) )
|
|
||||||
{
|
|
||||||
Q_EMIT q->instanceStarted();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sock->bytesAvailable() > 0) {
|
if( connectionType == NewInstance ||
|
||||||
Q_EMIT this->slotDataAvailable( sock, instanceId );
|
( connectionType == SecondaryInstance &&
|
||||||
}
|
options & SingleApplication::Mode::SecondaryNotification ) )
|
||||||
|
{
|
||||||
|
Q_EMIT q->instanceStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock->bytesAvailable() > 0){
|
||||||
|
Q_EMIT this->slotDataAvailable( sock, instanceId );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
|
void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
|
||||||
{
|
{
|
||||||
Q_Q(SingleApplication);
|
Q_Q(SingleApplication);
|
||||||
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
|
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
|
void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
|
||||||
{
|
{
|
||||||
if( closedSocket->bytesAvailable() > 0 )
|
if( closedSocket->bytesAvailable() > 0 )
|
||||||
Q_EMIT slotDataAvailable( closedSocket, instanceId );
|
Q_EMIT slotDataAvailable( closedSocket, instanceId );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleApplicationPrivate::randomSleep()
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 )
|
||||||
|
QThread::msleep( QRandomGenerator::global()->bounded( 8u, 18u ));
|
||||||
|
#else
|
||||||
|
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() );
|
||||||
|
QThread::msleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 ));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleApplicationPrivate::addAppData(const QString &data)
|
||||||
|
{
|
||||||
|
appDataList.push_back(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SingleApplicationPrivate::appData() const
|
||||||
|
{
|
||||||
|
return appDataList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) Itay Grudev 2015 - 2016
|
// Copyright (c) Itay Grudev 2015 - 2020
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -38,62 +38,67 @@
|
|||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
|
|
||||||
struct InstancesInfo {
|
struct InstancesInfo {
|
||||||
bool primary;
|
bool primary;
|
||||||
quint32 secondary;
|
quint32 secondary;
|
||||||
qint64 primaryPid;
|
qint64 primaryPid;
|
||||||
quint16 checksum;
|
char primaryUser[128];
|
||||||
|
quint16 checksum; // Must be the last field
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionInfo {
|
struct ConnectionInfo {
|
||||||
explicit ConnectionInfo() :
|
qint64 msgLen = 0;
|
||||||
msgLen(0), instanceId(0), stage(0) {}
|
quint32 instanceId = 0;
|
||||||
qint64 msgLen;
|
quint8 stage = 0;
|
||||||
quint32 instanceId;
|
|
||||||
quint8 stage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SingleApplicationPrivate : public QObject {
|
class SingleApplicationPrivate : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum ConnectionType : quint8 {
|
enum ConnectionType : quint8 {
|
||||||
InvalidConnection = 0,
|
InvalidConnection = 0,
|
||||||
NewInstance = 1,
|
NewInstance = 1,
|
||||||
SecondaryInstance = 2,
|
SecondaryInstance = 2,
|
||||||
Reconnect = 3
|
Reconnect = 3
|
||||||
};
|
};
|
||||||
enum ConnectionStage : quint8 {
|
enum ConnectionStage : quint8 {
|
||||||
StageHeader = 0,
|
StageHeader = 0,
|
||||||
StageBody = 1,
|
StageBody = 1,
|
||||||
StageConnected = 2,
|
StageConnected = 2,
|
||||||
};
|
};
|
||||||
Q_DECLARE_PUBLIC(SingleApplication)
|
Q_DECLARE_PUBLIC(SingleApplication)
|
||||||
|
|
||||||
SingleApplicationPrivate( SingleApplication *q_ptr );
|
SingleApplicationPrivate( SingleApplication *q_ptr );
|
||||||
~SingleApplicationPrivate();
|
~SingleApplicationPrivate() override;
|
||||||
|
|
||||||
void genBlockServerName();
|
static QString getUsername();
|
||||||
void initializeMemoryBlock();
|
void genBlockServerName();
|
||||||
void startPrimary();
|
void initializeMemoryBlock() const;
|
||||||
void startSecondary();
|
void startPrimary();
|
||||||
void connectToPrimary(int msecs, ConnectionType connectionType );
|
void startSecondary();
|
||||||
quint16 blockChecksum();
|
bool connectToPrimary( int msecs, ConnectionType connectionType );
|
||||||
qint64 primaryPid();
|
quint16 blockChecksum() const;
|
||||||
void readInitMessageHeader(QLocalSocket *socket);
|
qint64 primaryPid() const;
|
||||||
void readInitMessageBody(QLocalSocket *socket);
|
QString primaryUser() const;
|
||||||
|
void readInitMessageHeader(QLocalSocket *socket);
|
||||||
SingleApplication *q_ptr;
|
void readInitMessageBody(QLocalSocket *socket);
|
||||||
QSharedMemory *memory;
|
static void randomSleep();
|
||||||
QLocalSocket *socket;
|
void addAppData(const QString &data);
|
||||||
QLocalServer *server;
|
QStringList appData() const;
|
||||||
quint32 instanceNumber;
|
|
||||||
QString blockServerName;
|
SingleApplication *q_ptr;
|
||||||
SingleApplication::Options options;
|
QSharedMemory *memory;
|
||||||
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
QLocalSocket *socket;
|
||||||
|
QLocalServer *server;
|
||||||
public Q_SLOTS:
|
quint32 instanceNumber;
|
||||||
void slotConnectionEstablished();
|
QString blockServerName;
|
||||||
void slotDataAvailable( QLocalSocket*, quint32 );
|
SingleApplication::Options options;
|
||||||
void slotClientConnectionClosed( QLocalSocket*, quint32 );
|
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
||||||
|
QStringList appDataList;
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void slotConnectionEstablished();
|
||||||
|
void slotDataAvailable( QLocalSocket*, quint32 );
|
||||||
|
void slotClientConnectionClosed( QLocalSocket*, quint32 );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SINGLEAPPLICATION_P_H
|
#endif // SINGLEAPPLICATION_P_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "org.qelectrotech.QElectroTech",
|
"id": "org.qelectrotech.QElectroTech",
|
||||||
"runtime": "org.kde.Platform",
|
"runtime": "org.kde.Platform",
|
||||||
"runtime-version": "5.14",
|
"runtime-version": "5.15",
|
||||||
"sdk": "org.kde.Sdk",
|
"sdk": "org.kde.Sdk",
|
||||||
"command": "qelectrotech",
|
"command": "qelectrotech",
|
||||||
"rename-desktop-file": "qelectrotech.desktop",
|
"rename-desktop-file": "qelectrotech.desktop",
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ Include(FetchContent)
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
pugixml
|
pugixml
|
||||||
GIT_REPOSITORY https://github.com/zeux/pugixml.git
|
GIT_REPOSITORY https://github.com/zeux/pugixml.git
|
||||||
GIT_TAG v1.11.1)
|
GIT_TAG v1.11.4)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(pugixml)
|
FetchContent_MakeAvailable(pugixml)
|
||||||
|
|||||||
@@ -26,6 +26,6 @@ Include(FetchContent)
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
SingleApplication
|
SingleApplication
|
||||||
GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git
|
GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git
|
||||||
GIT_TAG v3.1.5)
|
GIT_TAG v3.2.0)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(SingleApplication)
|
FetchContent_MakeAvailable(SingleApplication)
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ set(QET_RES_FILES
|
|||||||
${QET_DIR}/sources/editor/ui/lineeditor.ui
|
${QET_DIR}/sources/editor/ui/lineeditor.ui
|
||||||
${QET_DIR}/sources/editor/ui/polygoneditor.ui
|
${QET_DIR}/sources/editor/ui/polygoneditor.ui
|
||||||
${QET_DIR}/sources/editor/ui/rectangleeditor.ui
|
${QET_DIR}/sources/editor/ui/rectangleeditor.ui
|
||||||
|
${QET_DIR}/sources/editor/ui/qetelementeditor.ui
|
||||||
|
${QET_DIR}/sources/editor/ui/terminaleditor.ui
|
||||||
${QET_DIR}/sources/ElementsCollection/ui/renamedialog.ui
|
${QET_DIR}/sources/ElementsCollection/ui/renamedialog.ui
|
||||||
${QET_DIR}/sources/factory/ui/addtabledialog.ui
|
${QET_DIR}/sources/factory/ui/addtabledialog.ui
|
||||||
${QET_DIR}/sources/NameList/ui/namelistdialog.ui
|
${QET_DIR}/sources/NameList/ui/namelistdialog.ui
|
||||||
@@ -260,12 +262,8 @@ set(QET_SRC_FILES
|
|||||||
${QET_DIR}/sources/editor/elementscene.h
|
${QET_DIR}/sources/editor/elementscene.h
|
||||||
${QET_DIR}/sources/editor/elementview.cpp
|
${QET_DIR}/sources/editor/elementview.cpp
|
||||||
${QET_DIR}/sources/editor/elementview.h
|
${QET_DIR}/sources/editor/elementview.h
|
||||||
${QET_DIR}/sources/editor/qetelementeditor.cpp
|
|
||||||
${QET_DIR}/sources/editor/qetelementeditor.h
|
|
||||||
${QET_DIR}/sources/editor/styleeditor.cpp
|
${QET_DIR}/sources/editor/styleeditor.cpp
|
||||||
${QET_DIR}/sources/editor/styleeditor.h
|
${QET_DIR}/sources/editor/styleeditor.h
|
||||||
${QET_DIR}/sources/editor/terminaleditor.cpp
|
|
||||||
${QET_DIR}/sources/editor/terminaleditor.h
|
|
||||||
|
|
||||||
${QET_DIR}/sources/editor/esevent/eseventaddarc.cpp
|
${QET_DIR}/sources/editor/esevent/eseventaddarc.cpp
|
||||||
${QET_DIR}/sources/editor/esevent/eseventaddarc.h
|
${QET_DIR}/sources/editor/esevent/eseventaddarc.h
|
||||||
@@ -320,8 +318,12 @@ set(QET_SRC_FILES
|
|||||||
${QET_DIR}/sources/editor/ui/polygoneditor.h
|
${QET_DIR}/sources/editor/ui/polygoneditor.h
|
||||||
${QET_DIR}/sources/editor/ui/rectangleeditor.cpp
|
${QET_DIR}/sources/editor/ui/rectangleeditor.cpp
|
||||||
${QET_DIR}/sources/editor/ui/rectangleeditor.h
|
${QET_DIR}/sources/editor/ui/rectangleeditor.h
|
||||||
|
${QET_DIR}/sources/editor/ui/terminaleditor.cpp
|
||||||
|
${QET_DIR}/sources/editor/ui/terminaleditor.h
|
||||||
${QET_DIR}/sources/editor/ui/texteditor.cpp
|
${QET_DIR}/sources/editor/ui/texteditor.cpp
|
||||||
${QET_DIR}/sources/editor/ui/texteditor.h
|
${QET_DIR}/sources/editor/ui/texteditor.h
|
||||||
|
${QET_DIR}/sources/editor/ui/qetelementeditor.h
|
||||||
|
${QET_DIR}/sources/editor/ui/qetelementeditor.cpp
|
||||||
|
|
||||||
${QET_DIR}/sources/editor/UndoCommand/pastepartscommand.cpp
|
${QET_DIR}/sources/editor/UndoCommand/pastepartscommand.cpp
|
||||||
${QET_DIR}/sources/editor/UndoCommand/pastepartscommand.h
|
${QET_DIR}/sources/editor/UndoCommand/pastepartscommand.h
|
||||||
@@ -371,6 +373,8 @@ set(QET_SRC_FILES
|
|||||||
${QET_DIR}/sources/print/projectprintwindow.cpp
|
${QET_DIR}/sources/print/projectprintwindow.cpp
|
||||||
${QET_DIR}/sources/print/projectprintwindow.h
|
${QET_DIR}/sources/print/projectprintwindow.h
|
||||||
|
|
||||||
|
${QET_DIR}/sources/properties/elementdata.cpp
|
||||||
|
${QET_DIR}/sources/properties/elementdata.h
|
||||||
${QET_DIR}/sources/properties/propertiesinterface.cpp
|
${QET_DIR}/sources/properties/propertiesinterface.cpp
|
||||||
${QET_DIR}/sources/properties/propertiesinterface.h
|
${QET_DIR}/sources/properties/propertiesinterface.h
|
||||||
${QET_DIR}/sources/properties/reportproperties.cpp
|
${QET_DIR}/sources/properties/reportproperties.cpp
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 309 KiB |
+712
-583
File diff suppressed because it is too large
Load Diff
+720
-591
File diff suppressed because it is too large
Load Diff
+712
-583
File diff suppressed because it is too large
Load Diff
+723
-592
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+723
-595
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+1006
-874
File diff suppressed because it is too large
Load Diff
+719
-590
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+721
-590
File diff suppressed because it is too large
Load Diff
+714
-585
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+708
-579
File diff suppressed because it is too large
Load Diff
+711
-582
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+718
-587
File diff suppressed because it is too large
Load Diff
+723
-594
File diff suppressed because it is too large
Load Diff
+712
-583
File diff suppressed because it is too large
Load Diff
+708
-579
File diff suppressed because it is too large
Load Diff
+712
-583
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+722
-591
File diff suppressed because it is too large
Load Diff
+720
-591
File diff suppressed because it is too large
Load Diff
+720
-588
File diff suppressed because it is too large
Load Diff
+714
-585
File diff suppressed because it is too large
Load Diff
+712
-583
File diff suppressed because it is too large
Load Diff
+712
-583
File diff suppressed because it is too large
Load Diff
+708
-579
File diff suppressed because it is too large
Load Diff
+708
-579
File diff suppressed because it is too large
Load Diff
+708
-579
File diff suppressed because it is too large
Load Diff
+712
-583
File diff suppressed because it is too large
Load Diff
+708
-579
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "elementscollectionwidget.h"
|
#include "elementscollectionwidget.h"
|
||||||
|
|
||||||
#include "../editor/qetelementeditor.h"
|
#include "../editor/ui/qetelementeditor.h"
|
||||||
#include "../elementscategoryeditor.h"
|
#include "../elementscategoryeditor.h"
|
||||||
#include "../newelementwizard.h"
|
#include "../newelementwizard.h"
|
||||||
#include "../qetapp.h"
|
#include "../qetapp.h"
|
||||||
@@ -38,6 +38,9 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
|
#include <QProgressBar>
|
||||||
|
#include <QStatusBar>
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief ElementsCollectionWidget::ElementsCollectionWidget
|
@brief ElementsCollectionWidget::ElementsCollectionWidget
|
||||||
|
|||||||
@@ -368,14 +368,6 @@ void ConductorProperties::fromXml(QDomElement &e)
|
|||||||
"vertical-alignment",
|
"vertical-alignment",
|
||||||
"AlignRight"
|
"AlignRight"
|
||||||
).toStdString().data()));
|
).toStdString().data()));
|
||||||
|
|
||||||
//Keep retrocompatible with version older than 0,4
|
|
||||||
//If the propertie @type is simple (removed since QET 0,4), we set text no visible.
|
|
||||||
//@TODO remove this code for qet 0.6 or later
|
|
||||||
#if TODO_LIST
|
|
||||||
#pragma message("@TODO remove this code for qet 0.6 or later")
|
|
||||||
#endif
|
|
||||||
if (e.attribute("type") == "simple") m_show_text = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -222,11 +222,6 @@ void DiagramEventAddElement::addElement()
|
|||||||
element -> setPos(m_element->pos());
|
element -> setPos(m_element->pos());
|
||||||
element -> setRotation(m_element -> rotation());
|
element -> setRotation(m_element -> rotation());
|
||||||
m_diagram -> addItem(element);
|
m_diagram -> addItem(element);
|
||||||
|
|
||||||
//The element is dropped by the user, the dynamic text field stored in m_converted_text_from_xml_description
|
|
||||||
//can be moved to m_dynamic_text_list, because we are sure fromXml will be not called.
|
|
||||||
element->m_dynamic_text_list.append(element->m_converted_text_from_xml_description.keys());
|
|
||||||
element->m_converted_text_from_xml_description.clear();
|
|
||||||
|
|
||||||
QUndoCommand *undo_object = new QUndoCommand(tr("Ajouter %1").arg(element->name()));
|
QUndoCommand *undo_object = new QUndoCommand(tr("Ajouter %1").arg(element->name()));
|
||||||
new AddGraphicsObjectCommand(element, m_diagram, m_element -> pos(), undo_object);
|
new AddGraphicsObjectCommand(element, m_diagram, m_element -> pos(), undo_object);
|
||||||
|
|||||||
@@ -282,13 +282,17 @@ ChangeNamesCommand::~ChangeNamesCommand()
|
|||||||
/// Annule le changement
|
/// Annule le changement
|
||||||
void ChangeNamesCommand::undo()
|
void ChangeNamesCommand::undo()
|
||||||
{
|
{
|
||||||
m_scene -> setNames(names_before);
|
auto data = m_scene->elementData();
|
||||||
|
data.m_names_list = names_before;
|
||||||
|
m_scene->setElementData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refait le changement
|
/// Refait le changement
|
||||||
void ChangeNamesCommand::redo()
|
void ChangeNamesCommand::redo()
|
||||||
{
|
{
|
||||||
m_scene -> setNames(names_after);
|
auto data = m_scene->elementData();
|
||||||
|
data.m_names_list = names_after;
|
||||||
|
m_scene->setElementData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -453,13 +457,17 @@ ChangeInformationsCommand::~ChangeInformationsCommand()
|
|||||||
/// Annule le changement d'autorisation pour les connexions internes
|
/// Annule le changement d'autorisation pour les connexions internes
|
||||||
void ChangeInformationsCommand::undo()
|
void ChangeInformationsCommand::undo()
|
||||||
{
|
{
|
||||||
m_scene -> setInformations(old_informations_);
|
auto data = m_scene->elementData();
|
||||||
|
data.m_drawing_information = old_informations_;
|
||||||
|
m_scene->setElementData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refait le changement d'autorisation pour les connexions internes
|
/// Refait le changement d'autorisation pour les connexions internes
|
||||||
void ChangeInformationsCommand::redo()
|
void ChangeInformationsCommand::redo()
|
||||||
{
|
{
|
||||||
m_scene -> setInformations(new_informations_);
|
auto data = m_scene->elementData();
|
||||||
|
data.m_drawing_information = new_informations_;
|
||||||
|
m_scene->setElementData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -572,45 +580,32 @@ void ScalePartsCommand::adjustText()
|
|||||||
setText(QObject::tr("redimensionnement de %1 primitives", "undo caption -- %1 always > 1").arg(scaled_primitives_.count()));
|
setText(QObject::tr("redimensionnement de %1 primitives", "undo caption -- %1 always > 1").arg(scaled_primitives_.count()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief ChangePropertiesCommand::ChangePropertiesCommand
|
* @brief changeElementDataCommand::changeElementDataCommand
|
||||||
Change the properties of the drawed element
|
* Change the properties of the drawed element
|
||||||
@param scene : scene to belong the property
|
* @param scene : scene to belong the property
|
||||||
@param type : new type of element.
|
* @param old_data : old data
|
||||||
@param info
|
* @param new_data : new data
|
||||||
@param elmt_info : new info about type.
|
* @param parent : parent undo command
|
||||||
@param parent : parent undo
|
*/
|
||||||
*/
|
changeElementDataCommand::changeElementDataCommand(ElementScene *scene,
|
||||||
ChangePropertiesCommand::ChangePropertiesCommand(
|
ElementData old_data,
|
||||||
ElementScene *scene,
|
ElementData new_data,
|
||||||
const QString& type,
|
QUndoCommand *parent) :
|
||||||
const DiagramContext& info,
|
ElementEditionCommand(scene, nullptr, parent),
|
||||||
const DiagramContext& elmt_info,
|
m_old(old_data),
|
||||||
QUndoCommand *parent) :
|
m_new(new_data)
|
||||||
ElementEditionCommand(scene, nullptr, parent)
|
|
||||||
{
|
{
|
||||||
m_type << scene->m_elmt_type << type;
|
setText(QObject::tr("Modifier les propriétées de l'élément"));
|
||||||
m_kind_info << scene->m_elmt_kindInfo << info;
|
|
||||||
m_elmt_info << scene->m_elmt_information << elmt_info;
|
|
||||||
setText(QObject::tr("Modifier les propriétés"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangePropertiesCommand::~ChangePropertiesCommand()
|
void changeElementDataCommand::undo() {
|
||||||
{}
|
m_scene->setElementData(m_old);
|
||||||
|
QUndoCommand::undo();
|
||||||
void ChangePropertiesCommand::undo()
|
|
||||||
{
|
|
||||||
m_scene->m_elmt_type = m_type.first();
|
|
||||||
m_scene->m_elmt_kindInfo = m_kind_info.first();
|
|
||||||
m_scene->setElementInfo(m_elmt_info.first());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangePropertiesCommand::redo()
|
void changeElementDataCommand::redo() {
|
||||||
{
|
m_scene->setElementData(m_new);
|
||||||
m_scene->m_elmt_type = m_type.last();
|
QUndoCommand::redo();
|
||||||
m_scene->m_elmt_kindInfo = m_kind_info.last();
|
|
||||||
m_scene->setElementInfo(m_elmt_info.last());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -262,23 +262,21 @@ class ScalePartsCommand : public ElementEditionCommand {
|
|||||||
bool first_redo;
|
bool first_redo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChangePropertiesCommand : public ElementEditionCommand {
|
class changeElementDataCommand : public ElementEditionCommand
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
ChangePropertiesCommand (
|
changeElementDataCommand(ElementScene *scene,
|
||||||
ElementScene *scene,
|
ElementData old_data,
|
||||||
const QString& type,
|
ElementData new_data,
|
||||||
const DiagramContext& info,
|
QUndoCommand *parent = nullptr);
|
||||||
const DiagramContext& elmt_info,
|
~changeElementDataCommand() override {}
|
||||||
QUndoCommand *parent=nullptr);
|
|
||||||
~ChangePropertiesCommand () override;
|
|
||||||
|
|
||||||
void undo() override;
|
void undo() override;
|
||||||
void redo() override;
|
void redo() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList <QString> m_type;
|
ElementData m_old,
|
||||||
QList <DiagramContext> m_kind_info;
|
m_new;
|
||||||
QList < DiagramContext> m_elmt_info;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include "elementitemeditor.h"
|
#include "elementitemeditor.h"
|
||||||
#include "qetelementeditor.h"
|
#include "ui/qetelementeditor.h"
|
||||||
#include "editorcommands.h"
|
#include "editorcommands.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+55
-105
@@ -33,7 +33,7 @@
|
|||||||
#include "graphicspart/partrectangle.h"
|
#include "graphicspart/partrectangle.h"
|
||||||
#include "graphicspart/partterminal.h"
|
#include "graphicspart/partterminal.h"
|
||||||
#include "graphicspart/parttext.h"
|
#include "graphicspart/parttext.h"
|
||||||
#include "qetelementeditor.h"
|
#include "ui/qetelementeditor.h"
|
||||||
#include "ui/elementpropertieseditorwidget.h"
|
#include "ui/elementpropertieseditorwidget.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
@@ -51,7 +51,6 @@
|
|||||||
*/
|
*/
|
||||||
ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
|
ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
|
||||||
QGraphicsScene(parent),
|
QGraphicsScene(parent),
|
||||||
m_elmt_type("simple"),
|
|
||||||
m_qgi_manager(this),
|
m_qgi_manager(this),
|
||||||
m_element_editor(editor)
|
m_element_editor(editor)
|
||||||
{
|
{
|
||||||
@@ -71,7 +70,25 @@ ElementScene::ElementScene(QETElementEditor *editor, QObject *parent) :
|
|||||||
connect(&m_undo_stack, SIGNAL(indexChanged(int)),
|
connect(&m_undo_stack, SIGNAL(indexChanged(int)),
|
||||||
this, SLOT(managePrimitivesGroups()));
|
this, SLOT(managePrimitivesGroups()));
|
||||||
connect(this, SIGNAL(selectionChanged()),
|
connect(this, SIGNAL(selectionChanged()),
|
||||||
this, SLOT(managePrimitivesGroups()));
|
this, SLOT(managePrimitivesGroups()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ElementScene::elementData
|
||||||
|
* @return the elementdata using by the scene
|
||||||
|
*/
|
||||||
|
ElementData ElementScene::elementData() {
|
||||||
|
return m_element_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElementScene::setElementData(ElementData data)
|
||||||
|
{
|
||||||
|
bool emit_ = m_element_data.m_informations != data.m_informations;
|
||||||
|
|
||||||
|
m_element_data = data;
|
||||||
|
|
||||||
|
if (emit_)
|
||||||
|
emit elementInfoChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -437,7 +454,7 @@ const QDomDocument ElementScene::toXml(bool all_parts)
|
|||||||
-(qRound(size.y() - (ymargin/2)))));
|
-(qRound(size.y() - (ymargin/2)))));
|
||||||
|
|
||||||
root.setAttribute("version", QET::version);
|
root.setAttribute("version", QET::version);
|
||||||
root.setAttribute("link_type", m_elmt_type);
|
root.setAttribute("link_type", m_element_data.typeToString(m_element_data.m_type));
|
||||||
|
|
||||||
//Uuid used to compare two elements
|
//Uuid used to compare two elements
|
||||||
QDomElement uuid = xml_document.createElement("uuid");
|
QDomElement uuid = xml_document.createElement("uuid");
|
||||||
@@ -445,29 +462,29 @@ const QDomDocument ElementScene::toXml(bool all_parts)
|
|||||||
root.appendChild(uuid);
|
root.appendChild(uuid);
|
||||||
|
|
||||||
//names of element
|
//names of element
|
||||||
root.appendChild(m_names_list.toXml(xml_document));
|
root.appendChild(m_element_data.m_names_list.toXml(xml_document));
|
||||||
|
|
||||||
if (m_elmt_type == "slave" || m_elmt_type == "master")
|
auto type_ = m_element_data.m_type;
|
||||||
|
if (type_ == ElementData::Slave ||
|
||||||
|
type_ == ElementData::Master ||
|
||||||
|
type_ == ElementData::Terminale)
|
||||||
{
|
{
|
||||||
QDomElement kindInfo = xml_document.createElement("kindInformations");
|
root.appendChild(m_element_data.kindInfoToXml(xml_document));
|
||||||
m_elmt_kindInfo.toXml(kindInfo, "kindInformation");
|
|
||||||
root.appendChild(kindInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if(type_ == ElementData::Simple ||
|
||||||
m_elmt_type == "simple"
|
type_ == ElementData::Master ||
|
||||||
|| m_elmt_type == "master"
|
type_ == ElementData::Terminale)
|
||||||
|| m_elmt_type == "terminal")
|
|
||||||
{
|
{
|
||||||
QDomElement element_info = xml_document.createElement("elementInformations");
|
QDomElement element_info = xml_document.createElement("elementInformations");
|
||||||
m_elmt_information.toXml(element_info, "elementInformation");
|
m_element_data.m_informations.toXml(element_info, "elementInformation");
|
||||||
root.appendChild(element_info);
|
root.appendChild(element_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
//complementary information about the element
|
//complementary information about the element
|
||||||
QDomElement informations_element = xml_document.createElement("informations");
|
QDomElement informations_element = xml_document.createElement("informations");
|
||||||
root.appendChild(informations_element);
|
root.appendChild(informations_element);
|
||||||
informations_element.appendChild(xml_document.createTextNode(informations()));
|
informations_element.appendChild(xml_document.createTextNode(m_element_data.m_drawing_information));
|
||||||
|
|
||||||
QDomElement description = xml_document.createElement("description");
|
QDomElement description = xml_document.createElement("description");
|
||||||
|
|
||||||
@@ -545,9 +562,16 @@ void ElementScene::fromXml(
|
|||||||
{
|
{
|
||||||
bool state = true;
|
bool state = true;
|
||||||
|
|
||||||
//Consider the informations of the element
|
//Consider the informations of the element
|
||||||
if (consider_informations) {
|
if (consider_informations)
|
||||||
state = applyInformations(xml_document);
|
{
|
||||||
|
// Root must be an element definition
|
||||||
|
QDomElement root = xml_document.documentElement();
|
||||||
|
|
||||||
|
if (root.tagName() == "definition" &&
|
||||||
|
root.attribute("type") == "element") {
|
||||||
|
m_element_data.fromXml(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state)
|
if (state)
|
||||||
@@ -699,19 +723,6 @@ QETElementEditor* ElementScene::editor() const
|
|||||||
return m_element_editor;
|
return m_element_editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
@brief ElementScene::setElementInfo
|
|
||||||
@param dc
|
|
||||||
*/
|
|
||||||
void ElementScene::setElementInfo(const DiagramContext& dc)
|
|
||||||
{
|
|
||||||
if(m_elmt_information != dc)
|
|
||||||
{
|
|
||||||
m_elmt_information = dc;
|
|
||||||
emit elementInfoChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief ElementScene::slot_select
|
@brief ElementScene::slot_select
|
||||||
Select the item in content,
|
Select the item in content,
|
||||||
@@ -833,7 +844,7 @@ void ElementScene::slot_editAuthorInformations()
|
|||||||
// ajoute un QTextEdit au dialogue
|
// ajoute un QTextEdit au dialogue
|
||||||
QTextEdit *text_field = new QTextEdit();
|
QTextEdit *text_field = new QTextEdit();
|
||||||
text_field -> setAcceptRichText(false);
|
text_field -> setAcceptRichText(false);
|
||||||
text_field -> setPlainText(informations());
|
text_field -> setPlainText(m_element_data.m_drawing_information);
|
||||||
text_field -> setReadOnly(is_read_only);
|
text_field -> setReadOnly(is_read_only);
|
||||||
dialog_layout -> addWidget(text_field);
|
dialog_layout -> addWidget(text_field);
|
||||||
|
|
||||||
@@ -851,10 +862,10 @@ void ElementScene::slot_editAuthorInformations()
|
|||||||
if (dialog_author.exec() == QDialog::Accepted && !is_read_only)
|
if (dialog_author.exec() == QDialog::Accepted && !is_read_only)
|
||||||
{
|
{
|
||||||
QString new_infos = text_field -> toPlainText().remove(QChar(13)); // CR-less text
|
QString new_infos = text_field -> toPlainText().remove(QChar(13)); // CR-less text
|
||||||
if (new_infos != informations())
|
if (new_infos != m_element_data.m_drawing_information)
|
||||||
{
|
{
|
||||||
undoStack().push(new ChangeInformationsCommand(
|
undoStack().push(new ChangeInformationsCommand(
|
||||||
this, informations(), new_infos));
|
this, m_element_data.m_drawing_information, new_infos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -865,20 +876,15 @@ void ElementScene::slot_editAuthorInformations()
|
|||||||
*/
|
*/
|
||||||
void ElementScene::slot_editProperties()
|
void ElementScene::slot_editProperties()
|
||||||
{
|
{
|
||||||
QString type = m_elmt_type;
|
ElementPropertiesEditorWidget epew(m_element_data);
|
||||||
DiagramContext kind_info = m_elmt_kindInfo;
|
|
||||||
DiagramContext elmt_info = m_elmt_information;
|
|
||||||
|
|
||||||
ElementPropertiesEditorWidget epew(type, kind_info, elmt_info);
|
|
||||||
epew.exec();
|
epew.exec();
|
||||||
|
|
||||||
if (type != m_elmt_type ||
|
if (m_element_data != epew.editedData())
|
||||||
kind_info != m_elmt_kindInfo ||
|
{
|
||||||
elmt_info != m_elmt_information)
|
undoStack().push(new changeElementDataCommand(this,
|
||||||
undoStack().push(new ChangePropertiesCommand(this,
|
m_element_data,
|
||||||
type,
|
epew.editedData()));
|
||||||
kind_info,
|
}
|
||||||
elmt_info));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -898,15 +904,15 @@ void ElementScene::slot_editNames()
|
|||||||
dialog_.setInformationText(tr("Vous pouvez spécifier le nom de l'élément dans plusieurs langues."));
|
dialog_.setInformationText(tr("Vous pouvez spécifier le nom de l'élément dans plusieurs langues."));
|
||||||
|
|
||||||
NameListWidget *nlw_ = dialog_.namelistWidget();
|
NameListWidget *nlw_ = dialog_.namelistWidget();
|
||||||
nlw_->setNames(m_names_list);
|
nlw_->setNames(m_element_data.m_names_list);
|
||||||
nlw_->setReadOnly(is_read_only);
|
nlw_->setReadOnly(is_read_only);
|
||||||
|
|
||||||
if (dialog_.exec() == QDialog::Accepted && !is_read_only && !nlw_->isEmpty())
|
if (dialog_.exec() == QDialog::Accepted && !is_read_only && !nlw_->isEmpty())
|
||||||
{
|
{
|
||||||
NamesList new_names = nlw_->names();
|
NamesList new_names = nlw_->names();
|
||||||
if (new_names != m_names_list) {
|
if (new_names != m_element_data. m_names_list) {
|
||||||
undoStack().push(new ChangeNamesCommand(this,
|
undoStack().push(new ChangeNamesCommand(this,
|
||||||
m_names_list,
|
m_element_data.m_names_list,
|
||||||
new_names));
|
new_names));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1087,62 +1093,6 @@ QRectF ElementScene::elementContentBoundingRect(
|
|||||||
return(bounding_rect);
|
return(bounding_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
@brief ElementScene::applyInformations
|
|
||||||
Applies the information (dimensions, hostpot, orientations,
|
|
||||||
internal connections, names and additional information)
|
|
||||||
contained in an XML document.
|
|
||||||
\~French Applique les informations (dimensions, hostpot, orientations,
|
|
||||||
connexions internes, noms et informations complementaires)
|
|
||||||
contenu dans un document XML.
|
|
||||||
\~ @param xml_document : Document XML a analyser
|
|
||||||
\~ @return
|
|
||||||
true if reading and applying the information went well, false otherwise.
|
|
||||||
\~French true si la lecture et l'application
|
|
||||||
des informations s'est bien passee, false sinon.
|
|
||||||
*/
|
|
||||||
bool ElementScene::applyInformations(const QDomDocument &xml_document)
|
|
||||||
{
|
|
||||||
// Root must be an element definition
|
|
||||||
QDomElement root = xml_document.documentElement();
|
|
||||||
|
|
||||||
if (
|
|
||||||
root.tagName() != "definition"
|
|
||||||
||
|
|
||||||
root.attribute("type") != "element")
|
|
||||||
return(false);
|
|
||||||
|
|
||||||
//Extract info about element type
|
|
||||||
m_elmt_type = root.attribute("link_type", "simple");
|
|
||||||
m_elmt_kindInfo.fromXml(
|
|
||||||
root.firstChildElement("kindInformations"),
|
|
||||||
"kindInformation");
|
|
||||||
//Extract info of element
|
|
||||||
m_elmt_information.fromXml(
|
|
||||||
root.firstChildElement("elementInformations"),
|
|
||||||
"elementInformation");
|
|
||||||
|
|
||||||
//Extract names of xml definition
|
|
||||||
m_names_list.fromXml(root);
|
|
||||||
|
|
||||||
//extract additional informations
|
|
||||||
setInformations(QString());
|
|
||||||
for (QDomNode node = root.firstChild() ;
|
|
||||||
!node.isNull() ;
|
|
||||||
node = node.nextSibling())
|
|
||||||
{
|
|
||||||
QDomElement elmt = node.toElement();
|
|
||||||
if (elmt.isNull()) continue;
|
|
||||||
if (elmt.tagName() == "informations")
|
|
||||||
{
|
|
||||||
setInformations(elmt.text());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief ElementScene::loadContent
|
@brief ElementScene::loadContent
|
||||||
Create and load the content describe in the xml document.
|
Create and load the content describe in the xml document.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "../diagramcontext.h"
|
#include "../diagramcontext.h"
|
||||||
#include "../qgimanager.h"
|
#include "../qgimanager.h"
|
||||||
#include "elementcontent.h"
|
#include "elementcontent.h"
|
||||||
|
#include "../properties/elementdata.h"
|
||||||
|
|
||||||
#include <QtWidgets>
|
#include <QtWidgets>
|
||||||
#include <QtXml>
|
#include <QtXml>
|
||||||
@@ -65,11 +66,7 @@ class ElementScene : public QGraphicsScene
|
|||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
private:
|
private:
|
||||||
NamesList m_names_list; /// List of localized names
|
ElementData m_element_data; ///ElementData. Actualy in transition with old data storage
|
||||||
QString m_informations; /// Extra informations
|
|
||||||
QString m_elmt_type; /// element type
|
|
||||||
DiagramContext m_elmt_kindInfo,
|
|
||||||
m_elmt_information; /// element kind info
|
|
||||||
QGIManager m_qgi_manager;
|
QGIManager m_qgi_manager;
|
||||||
QUndoStack m_undo_stack;
|
QUndoStack m_undo_stack;
|
||||||
|
|
||||||
@@ -90,21 +87,20 @@ class ElementScene : public QGraphicsScene
|
|||||||
|
|
||||||
// methods
|
// methods
|
||||||
public:
|
public:
|
||||||
|
ElementData elementData();
|
||||||
|
void setElementData(ElementData data);
|
||||||
|
|
||||||
void setEventInterface (ESEventInterface *event_interface);
|
void setEventInterface (ESEventInterface *event_interface);
|
||||||
void clearEventInterface();
|
void clearEventInterface();
|
||||||
|
|
||||||
void setBehavior (ElementScene::Behavior);
|
void setBehavior (ElementScene::Behavior);
|
||||||
ElementScene::Behavior behavior() const;
|
ElementScene::Behavior behavior() const;
|
||||||
|
|
||||||
QPointF snapToGrid(QPointF point);
|
QPointF snapToGrid(QPointF point);
|
||||||
void setNames(const NamesList &);
|
|
||||||
NamesList names() const;
|
|
||||||
QString informations() const;
|
|
||||||
void setInformations(const QString &);
|
|
||||||
QString elementType () const {return m_elmt_type;}
|
|
||||||
DiagramContext elementKindInfo () const {return m_elmt_kindInfo;}
|
|
||||||
DiagramContext elementInformation() const {return m_elmt_information;}
|
|
||||||
virtual int xGrid() const;
|
virtual int xGrid() const;
|
||||||
virtual int yGrid() const;
|
virtual int yGrid() const;
|
||||||
virtual void setGrid(int, int);
|
virtual void setGrid(int, int);
|
||||||
|
|
||||||
virtual const QDomDocument toXml(bool = true);
|
virtual const QDomDocument toXml(bool = true);
|
||||||
virtual QRectF boundingRectFromXml(const QDomDocument &);
|
virtual QRectF boundingRectFromXml(const QDomDocument &);
|
||||||
virtual void fromXml(const QDomDocument &,
|
virtual void fromXml(const QDomDocument &,
|
||||||
@@ -128,7 +124,6 @@ class ElementScene : public QGraphicsScene
|
|||||||
void cut();
|
void cut();
|
||||||
void copy();
|
void copy();
|
||||||
QETElementEditor* editor() const;
|
QETElementEditor* editor() const;
|
||||||
void setElementInfo(const DiagramContext& dc);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mouseMoveEvent (QGraphicsSceneMouseEvent *) override;
|
void mouseMoveEvent (QGraphicsSceneMouseEvent *) override;
|
||||||
@@ -137,12 +132,10 @@ class ElementScene : public QGraphicsScene
|
|||||||
void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override;
|
void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override;
|
||||||
void keyPressEvent (QKeyEvent *event) override;
|
void keyPressEvent (QKeyEvent *event) override;
|
||||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
|
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
|
||||||
|
|
||||||
void drawForeground(QPainter *, const QRectF &) override;
|
void drawForeground(QPainter *, const QRectF &) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QRectF elementContentBoundingRect(const ElementContent &) const;
|
QRectF elementContentBoundingRect(const ElementContent &) const;
|
||||||
bool applyInformations(const QDomDocument &);
|
|
||||||
ElementContent loadContent(const QDomDocument &);
|
ElementContent loadContent(const QDomDocument &);
|
||||||
ElementContent addContent(const ElementContent &);
|
ElementContent addContent(const ElementContent &);
|
||||||
ElementContent addContentAtPos(const ElementContent &, const QPointF &);
|
ElementContent addContentAtPos(const ElementContent &, const QPointF &);
|
||||||
@@ -180,39 +173,4 @@ class ElementScene : public QGraphicsScene
|
|||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ElementScene::ItemOptions)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(ElementScene::ItemOptions)
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief ElementScene::setNames
|
|
||||||
@param nameslist New set of naes for the currently edited element
|
|
||||||
*/
|
|
||||||
inline void ElementScene::setNames(const NamesList &nameslist) {
|
|
||||||
m_names_list = nameslist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief ElementScene::names
|
|
||||||
@return the list of names of the currently edited element
|
|
||||||
*/
|
|
||||||
inline NamesList ElementScene::names() const
|
|
||||||
{
|
|
||||||
return(m_names_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief ElementScene::informations
|
|
||||||
@return extra informations of the currently edited element
|
|
||||||
*/
|
|
||||||
inline QString ElementScene::informations() const
|
|
||||||
{
|
|
||||||
return(m_informations);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief ElementScene::setInformations
|
|
||||||
@param infos new extra information for the currently edited element
|
|
||||||
*/
|
|
||||||
inline void ElementScene::setInformations(const QString &infos) {
|
|
||||||
m_informations = infos;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "../qetapp.h"
|
#include "../qetapp.h"
|
||||||
#include "UndoCommand/pastepartscommand.h"
|
#include "UndoCommand/pastepartscommand.h"
|
||||||
#include "qetelementeditor.h"
|
#include "ui/qetelementeditor.h"
|
||||||
/**
|
/**
|
||||||
Constructeur
|
Constructeur
|
||||||
@param scene ElementScene visualisee par cette ElementView
|
@param scene ElementScene visualisee par cette ElementView
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#include "../editorcommands.h"
|
#include "../editorcommands.h"
|
||||||
#include "../elementscene.h"
|
#include "../elementscene.h"
|
||||||
#include "../graphicspart/partline.h"
|
#include "../graphicspart/partline.h"
|
||||||
#include "../qetelementeditor.h"
|
#include "../ui/qetelementeditor.h"
|
||||||
|
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
#include "eseventinterface.h"
|
#include "eseventinterface.h"
|
||||||
|
|
||||||
#include "../elementscene.h"
|
#include "../elementscene.h"
|
||||||
#include "../qetelementeditor.h"
|
#include "../ui/qetelementeditor.h"
|
||||||
|
#include "../elementview.h"
|
||||||
|
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ ESEventInterface::ESEventInterface(ElementScene *scene) :
|
|||||||
void ESEventInterface::init()
|
void ESEventInterface::init()
|
||||||
{
|
{
|
||||||
m_scene->setBehavior(ElementScene::Behavior::AddPart);
|
m_scene->setBehavior(ElementScene::Behavior::AddPart);
|
||||||
m_editor->slot_setNoDragToView();
|
m_editor->elementView()->setDragMode(QGraphicsView::NoDrag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,31 +54,31 @@ ESEventInterface::~ESEventInterface()
|
|||||||
delete m_help_verti;
|
delete m_help_verti;
|
||||||
|
|
||||||
m_scene->setBehavior(ElementScene::Behavior::Normal);
|
m_scene->setBehavior(ElementScene::Behavior::Normal);
|
||||||
m_editor->slot_setRubberBandToView();
|
m_editor->elementView()->setDragMode(QGraphicsView::RubberBandDrag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESEventInterface::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
|
bool ESEventInterface::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
Q_UNUSED (event);
|
Q_UNUSED (event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESEventInterface::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
bool ESEventInterface::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
Q_UNUSED (event);
|
Q_UNUSED (event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESEventInterface::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
bool ESEventInterface::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
Q_UNUSED (event);
|
Q_UNUSED (event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESEventInterface::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
bool ESEventInterface::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
Q_UNUSED (event);
|
Q_UNUSED (event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ESEventInterface::wheelEvent(QGraphicsSceneWheelEvent *event) {
|
bool ESEventInterface::wheelEvent(QGraphicsSceneWheelEvent *event) {
|
||||||
Q_UNUSED (event);
|
Q_UNUSED (event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ bool ESEventInterface::keyPressEvent(QKeyEvent *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ESEventInterface::KeyReleaseEvent(QKeyEvent *event) {
|
bool ESEventInterface::KeyReleaseEvent(QKeyEvent *event) {
|
||||||
Q_UNUSED (event);
|
Q_UNUSED (event)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1264,24 +1264,6 @@ void CustomElementGraphicPart::drawShadowShape(QPainter *painter)
|
|||||||
painter -> restore ();
|
painter -> restore ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
@brief CustomElementGraphicPart::itemChange
|
|
||||||
Reimplemented from QGraphicsObject.
|
|
||||||
If the item position change call updateCurrentPartEditor()
|
|
||||||
the change is always send to QGraphicsObject
|
|
||||||
@param change
|
|
||||||
@param value
|
|
||||||
@return the returned value of QGraphicsObject::itemChange
|
|
||||||
*/
|
|
||||||
QVariant CustomElementGraphicPart::itemChange(GraphicsItemChange change, const QVariant &value)
|
|
||||||
{
|
|
||||||
if (scene())
|
|
||||||
if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemPositionHasChanged)
|
|
||||||
updateCurrentPartEditor();
|
|
||||||
|
|
||||||
return(QGraphicsObject::itemChange(change, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief CustomElementGraphicPart::hoverEnterEvent
|
@brief CustomElementGraphicPart::hoverEnterEvent
|
||||||
Reimplemented from QGraphicsObject.
|
Reimplemented from QGraphicsObject.
|
||||||
|
|||||||
@@ -309,8 +309,6 @@ class CustomElementGraphicPart : public QGraphicsObject, public CustomElementPar
|
|||||||
void applyStylesToQPainter(QPainter &) const;
|
void applyStylesToQPainter(QPainter &) const;
|
||||||
void drawShadowShape (QPainter *painter);
|
void drawShadowShape (QPainter *painter);
|
||||||
|
|
||||||
QVariant itemChange(GraphicsItemChange change,
|
|
||||||
const QVariant &value) override;
|
|
||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
#include "customelementpart.h"
|
#include "customelementpart.h"
|
||||||
|
|
||||||
#include "../qetelementeditor.h"
|
#include "../ui/qetelementeditor.h"
|
||||||
|
#include "../elementscene.h"
|
||||||
|
|
||||||
/// @return le QETElementEditor auquel cet editeur appartient
|
/// @return le QETElementEditor auquel cet editeur appartient
|
||||||
QETElementEditor *CustomElementPart::elementEditor() const
|
QETElementEditor *CustomElementPart::elementEditor() const
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ void PartDynamicTextField::setText(const QString &text) {
|
|||||||
void PartDynamicTextField::setInfoName(const QString &info_name) {
|
void PartDynamicTextField::setInfoName(const QString &info_name) {
|
||||||
m_info_name = info_name;
|
m_info_name = info_name;
|
||||||
if(m_text_from == DynamicElementTextItem::ElementInfo && elementScene())
|
if(m_text_from == DynamicElementTextItem::ElementInfo && elementScene())
|
||||||
setPlainText(elementScene() -> elementInformation().value(m_info_name).toString());
|
setPlainText(elementScene()->elementData().m_informations.value(m_info_name).toString());
|
||||||
emit infoNameChanged(m_info_name);
|
emit infoNameChanged(m_info_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +338,7 @@ QString PartDynamicTextField::infoName() const{
|
|||||||
void PartDynamicTextField::setCompositeText(const QString &text) {
|
void PartDynamicTextField::setCompositeText(const QString &text) {
|
||||||
m_composite_text = text;
|
m_composite_text = text;
|
||||||
if(m_text_from == DynamicElementTextItem::CompositeText && elementScene())
|
if(m_text_from == DynamicElementTextItem::CompositeText && elementScene())
|
||||||
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementScene() -> elementInformation()));
|
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementScene()->elementData().m_informations));
|
||||||
emit compositeTextChanged(m_composite_text);
|
emit compositeTextChanged(m_composite_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,10 +551,10 @@ void PartDynamicTextField::elementInfoChanged()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if(m_text_from == DynamicElementTextItem::ElementInfo)
|
if(m_text_from == DynamicElementTextItem::ElementInfo)
|
||||||
setPlainText(elementScene() -> elementInformation().value(m_info_name).toString());
|
setPlainText(elementScene()->elementData().m_informations.value(m_info_name).toString());
|
||||||
else if (m_text_from == DynamicElementTextItem::CompositeText && elementScene())
|
else if (m_text_from == DynamicElementTextItem::CompositeText && elementScene())
|
||||||
setPlainText(autonum::AssignVariables::replaceVariable(
|
setPlainText(autonum::AssignVariables::replaceVariable(
|
||||||
m_composite_text, elementScene() -> elementInformation()));
|
m_composite_text, elementScene()->elementData().m_informations));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartDynamicTextField::prepareAlignment()
|
void PartDynamicTextField::prepareAlignment()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "../../QetGraphicsItemModeler/qetgraphicshandlerutility.h"
|
#include "../../QetGraphicsItemModeler/qetgraphicshandlerutility.h"
|
||||||
#include "../../qeticons.h"
|
#include "../../qeticons.h"
|
||||||
#include "../elementscene.h"
|
#include "../elementscene.h"
|
||||||
#include "../qetelementeditor.h"
|
#include "../ui/qetelementeditor.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief PartPolygon::PartPolygon
|
@brief PartPolygon::PartPolygon
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ void PartTerminal::paint(
|
|||||||
const QStyleOptionGraphicsItem *options,
|
const QStyleOptionGraphicsItem *options,
|
||||||
QWidget *widget)
|
QWidget *widget)
|
||||||
{
|
{
|
||||||
Q_UNUSED(widget);
|
Q_UNUSED(widget)
|
||||||
painter -> save();
|
painter -> save();
|
||||||
|
|
||||||
// annulation des renderhints
|
// annulation des renderhints
|
||||||
@@ -98,7 +98,7 @@ void PartTerminal::paint(
|
|||||||
// dessin de la borne en rouge
|
// dessin de la borne en rouge
|
||||||
t.setColor(isSelected() ? Terminal::neutralColor : Qt::red);
|
t.setColor(isSelected() ? Terminal::neutralColor : Qt::red);
|
||||||
painter -> setPen(t);
|
painter -> setPen(t);
|
||||||
painter -> drawLine(QPointF(0.0, 0.0), d -> second_point);
|
painter -> drawLine(QPointF(0.0, 0.0), d -> m_second_point);
|
||||||
|
|
||||||
// dessin du point d'amarrage au conducteur en bleu
|
// dessin du point d'amarrage au conducteur en bleu
|
||||||
t.setColor(isSelected() ? Qt::red : Terminal::neutralColor);
|
t.setColor(isSelected() ? Qt::red : Terminal::neutralColor);
|
||||||
@@ -118,7 +118,7 @@ void PartTerminal::paint(
|
|||||||
QPainterPath PartTerminal::shape() const
|
QPainterPath PartTerminal::shape() const
|
||||||
{
|
{
|
||||||
QPainterPath shape;
|
QPainterPath shape;
|
||||||
shape.lineTo(d -> second_point);
|
shape.lineTo(d -> m_second_point);
|
||||||
|
|
||||||
QPainterPathStroker pps;
|
QPainterPathStroker pps;
|
||||||
pps.setWidth(1);
|
pps.setWidth(1);
|
||||||
@@ -132,7 +132,7 @@ QPainterPath PartTerminal::shape() const
|
|||||||
*/
|
*/
|
||||||
QRectF PartTerminal::boundingRect() const
|
QRectF PartTerminal::boundingRect() const
|
||||||
{
|
{
|
||||||
QRectF br(QPointF(0, 0), d -> second_point);
|
QRectF br(QPointF(0, 0), d -> m_second_point);
|
||||||
br = br.normalized();
|
br = br.normalized();
|
||||||
|
|
||||||
qreal adjust = (SHADOWS_HEIGHT + 1) / 2;
|
qreal adjust = (SHADOWS_HEIGHT + 1) / 2;
|
||||||
@@ -161,6 +161,20 @@ void PartTerminal::setName(QString& name) {
|
|||||||
emit nameChanged();
|
emit nameChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PartTerminal::setTerminalType
|
||||||
|
* Set the type of terminal to 'type'
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
void PartTerminal::setTerminalType(TerminalData::Type type)
|
||||||
|
{
|
||||||
|
if (d->m_type == type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->m_type = type;
|
||||||
|
emit terminalTypeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void PartTerminal::setNewUuid()
|
void PartTerminal::setNewUuid()
|
||||||
{
|
{
|
||||||
d -> m_uuid = QUuid::createUuid();
|
d -> m_uuid = QUuid::createUuid();
|
||||||
@@ -174,10 +188,10 @@ void PartTerminal::updateSecondPoint()
|
|||||||
{
|
{
|
||||||
qreal ts = 4.0; // terminal size
|
qreal ts = 4.0; // terminal size
|
||||||
switch(d -> m_orientation) {
|
switch(d -> m_orientation) {
|
||||||
case Qet::North: d -> second_point = QPointF(0.0, ts); break;
|
case Qet::North: d -> m_second_point = QPointF(0.0, ts); break;
|
||||||
case Qet::East : d -> second_point = QPointF(-ts, 0.0); break;
|
case Qet::East : d -> m_second_point = QPointF(-ts, 0.0); break;
|
||||||
case Qet::South: d -> second_point = QPointF(0.0, -ts); break;
|
case Qet::South: d -> m_second_point = QPointF(0.0, -ts); break;
|
||||||
case Qet::West : d -> second_point = QPointF(ts, 0.0); break;
|
case Qet::West : d -> m_second_point = QPointF(ts, 0.0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,13 @@
|
|||||||
This class represents a terminal which may be used to compose the drawing of
|
This class represents a terminal which may be used to compose the drawing of
|
||||||
an electrical element within the element editor.
|
an electrical element within the element editor.
|
||||||
*/
|
*/
|
||||||
class PartTerminal : public CustomElementGraphicPart {
|
class PartTerminal : public CustomElementGraphicPart
|
||||||
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(Qet::Orientation orientation READ orientation WRITE setOrientation)
|
Q_PROPERTY(Qet::Orientation orientation READ orientation WRITE setOrientation)
|
||||||
Q_PROPERTY(QString name READ name WRITE setName)
|
Q_PROPERTY(QString name READ name WRITE setName)
|
||||||
|
Q_PROPERTY(TerminalData::Type terminal_type READ terminalType WRITE setTerminalType)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// constructors, destructor
|
// constructors, destructor
|
||||||
@@ -42,6 +45,7 @@ class PartTerminal : public CustomElementGraphicPart {
|
|||||||
signals:
|
signals:
|
||||||
void orientationChanged();
|
void orientationChanged();
|
||||||
void nameChanged();
|
void nameChanged();
|
||||||
|
void terminalTypeChanged();
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
public:
|
public:
|
||||||
@@ -51,7 +55,6 @@ class PartTerminal : public CustomElementGraphicPart {
|
|||||||
@return the QGraphicsItem type
|
@return the QGraphicsItem type
|
||||||
*/
|
*/
|
||||||
int type() const override { return Type; }
|
int type() const override { return Type; }
|
||||||
QString name() const override { return d -> m_name; }
|
|
||||||
QString xmlName() const override { return(QString("terminal")); }
|
QString xmlName() const override { return(QString("terminal")); }
|
||||||
void fromXml(const QDomElement &) override;
|
void fromXml(const QDomElement &) override;
|
||||||
const QDomElement toXml(QDomDocument &) const override;
|
const QDomElement toXml(QDomDocument &) const override;
|
||||||
@@ -71,7 +74,12 @@ class PartTerminal : public CustomElementGraphicPart {
|
|||||||
Qet::Orientation orientation() const {return d -> m_orientation;}
|
Qet::Orientation orientation() const {return d -> m_orientation;}
|
||||||
void setOrientation(Qet::Orientation ori);
|
void setOrientation(Qet::Orientation ori);
|
||||||
|
|
||||||
|
QString name() const override { return d -> m_name; }
|
||||||
void setName(QString& name);
|
void setName(QString& name);
|
||||||
|
|
||||||
|
TerminalData::Type terminalType() const {return d->m_type;}
|
||||||
|
void setTerminalType(TerminalData::Type type);
|
||||||
|
|
||||||
void setNewUuid();
|
void setNewUuid();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2006-2021 The QElectroTech Team
|
|
||||||
This file is part of QElectroTech.
|
|
||||||
|
|
||||||
QElectroTech is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
QElectroTech is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef CUSTOM_ELEMENT_EDITOR_H
|
|
||||||
#define CUSTOM_ELEMENT_EDITOR_H
|
|
||||||
#include "../ElementsCollection/elementslocation.h"
|
|
||||||
#include "../qet.h"
|
|
||||||
#include "../qetmainwindow.h"
|
|
||||||
#include "elementscene.h"
|
|
||||||
|
|
||||||
class ElementItemEditor;
|
|
||||||
class ElementView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This class represents an element editor, allowing users to draw, change and
|
|
||||||
configure a particular electrical element.
|
|
||||||
*/
|
|
||||||
class QETElementEditor : public QETMainWindow {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
// constructor, destructor
|
|
||||||
public:
|
|
||||||
QETElementEditor(QWidget * = nullptr);
|
|
||||||
~QETElementEditor() override;
|
|
||||||
private:
|
|
||||||
QETElementEditor(const QETElementEditor &);
|
|
||||||
void setupActions();
|
|
||||||
void setupMenus();
|
|
||||||
void setupInterface();
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
private:
|
|
||||||
/// whether the editor is "read-only"
|
|
||||||
bool read_only;
|
|
||||||
/// menus
|
|
||||||
QMenu *file_menu, *edit_menu, *paste_from_menu, *display_menu, *tools_menu;
|
|
||||||
/// view widget for the editing scene
|
|
||||||
ElementView *m_view;
|
|
||||||
/// editing scene
|
|
||||||
ElementScene *m_elmt_scene;
|
|
||||||
/// container for widgets dedicated to primitive edition
|
|
||||||
QDockWidget *m_tools_dock;
|
|
||||||
/// Stack of widgets for tools_dock
|
|
||||||
QStackedWidget *m_tools_dock_stack;
|
|
||||||
/// label displayed when several primitives are selected
|
|
||||||
QLabel *m_default_informations;
|
|
||||||
/// Hash associating primitive names with their matching edition widget
|
|
||||||
QHash<QString, ElementItemEditor *> m_editors;
|
|
||||||
/// container for the undo list
|
|
||||||
QDockWidget *m_undo_dock;
|
|
||||||
/// Container for the list of existing primitives
|
|
||||||
QDockWidget *m_parts_dock;
|
|
||||||
/// List of primitives
|
|
||||||
QListWidget *m_parts_list;
|
|
||||||
/// actions for the "file" menu
|
|
||||||
QAction *new_element, *open, *open_dxf, *open_file, *save, *save_as, *save_as_file, *reload, *quit;
|
|
||||||
/// actions for the "edit" menu
|
|
||||||
QAction *selectall, *deselectall, *inv_select;
|
|
||||||
QAction *cut, *copy, *paste, *paste_in_area, *paste_from_file, *paste_from_elmt;
|
|
||||||
QAction *undo, *redo;
|
|
||||||
QAction *edit_delete, *edit_size_hs, *edit_names, *edit_author, *m_edit_properties;
|
|
||||||
/// toolbars
|
|
||||||
QToolBar *parts_toolbar, *main_toolbar, *view_toolbar, *depth_toolbar, *element_toolbar;
|
|
||||||
/// Action group
|
|
||||||
QActionGroup *parts, *m_zoom_ag, *m_depth_action_group;
|
|
||||||
/// minimum window title
|
|
||||||
QString min_title;
|
|
||||||
/// filename of the currently edited element
|
|
||||||
QString filename_;
|
|
||||||
/// location of the currently edited element
|
|
||||||
ElementsLocation location_;
|
|
||||||
/// whether the currently edited element comes from a file or a location
|
|
||||||
bool opened_from_file;
|
|
||||||
|
|
||||||
// methods
|
|
||||||
public:
|
|
||||||
void setNames(const NamesList &);
|
|
||||||
void setLocation(const ElementsLocation &);
|
|
||||||
ElementsLocation location() const;
|
|
||||||
void setFileName(const QString &);
|
|
||||||
QString fileName() const;
|
|
||||||
void setReadOnly(bool);
|
|
||||||
bool isReadOnly() const;
|
|
||||||
void fromFile(const QString &);
|
|
||||||
void fromLocation(const ElementsLocation &);
|
|
||||||
bool toFile(const QString &);
|
|
||||||
bool toLocation(const ElementsLocation &location);
|
|
||||||
bool isEditing(const ElementsLocation &);
|
|
||||||
bool isEditing(const QString &);
|
|
||||||
ElementScene *elementScene() const;
|
|
||||||
void readSettings();
|
|
||||||
void writeSettings();
|
|
||||||
static QPointF pasteOffset();
|
|
||||||
static QString getOpenElementFileName(QWidget * = nullptr, const QString & = QString());
|
|
||||||
void contextMenu(QPoint p, QList<QAction *> actions = QList<QAction*>());
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void saveToLocation(ElementsLocation loc);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void closeEvent(QCloseEvent *) override;
|
|
||||||
void firstActivation(QEvent *) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool canClose();
|
|
||||||
QWidget *clearToolsDock();
|
|
||||||
void copyAndPasteXml(const QDomDocument &);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void addLine();
|
|
||||||
void addRect();
|
|
||||||
void addEllipse();
|
|
||||||
void addPolygon();
|
|
||||||
void addArc();
|
|
||||||
void addText();
|
|
||||||
void addTerminal();
|
|
||||||
void addDynamicTextField();
|
|
||||||
void UncheckAddPrimitive();
|
|
||||||
|
|
||||||
void slot_new();
|
|
||||||
void slot_open();
|
|
||||||
void slot_openDxf();
|
|
||||||
void slot_openFile();
|
|
||||||
void openRecentFile(const QString &);
|
|
||||||
void openElement(const QString &);
|
|
||||||
void slot_reload();
|
|
||||||
bool slot_save();
|
|
||||||
bool slot_saveAs();
|
|
||||||
bool slot_saveAsFile();
|
|
||||||
void slot_setRubberBandToView();
|
|
||||||
void slot_setNoDragToView();
|
|
||||||
void slot_updateInformations();
|
|
||||||
void slot_updateMenus();
|
|
||||||
void slot_updateTitle();
|
|
||||||
void slot_createPartsList();
|
|
||||||
void slot_updatePartsList();
|
|
||||||
void slot_updateSelectionFromPartsList();
|
|
||||||
bool checkElement();
|
|
||||||
void pasteFromFile();
|
|
||||||
void pasteFromElement();
|
|
||||||
void updateCurrentPartEditor();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
@param nameslist the new list of names for the currently edited element
|
|
||||||
*/
|
|
||||||
inline void QETElementEditor::setNames(const NamesList &nameslist) {
|
|
||||||
m_elmt_scene -> setNames(nameslist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return the location of the currently edited element
|
|
||||||
*/
|
|
||||||
inline ElementsLocation QETElementEditor::location() const
|
|
||||||
{
|
|
||||||
return(location_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return the filename of the currently edited element
|
|
||||||
*/
|
|
||||||
inline QString QETElementEditor::fileName() const
|
|
||||||
{
|
|
||||||
return(filename_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return the editing scene
|
|
||||||
*/
|
|
||||||
inline ElementScene *QETElementEditor::elementScene() const
|
|
||||||
{
|
|
||||||
return(m_elmt_scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,322 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2006-2021 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 "terminaleditor.h"
|
|
||||||
|
|
||||||
#include "../QPropertyUndoCommand/qpropertyundocommand.h"
|
|
||||||
#include "../editor/graphicspart/partterminal.h"
|
|
||||||
#include "../qeticons.h"
|
|
||||||
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::TerminalEditor
|
|
||||||
@param editor
|
|
||||||
@param parent
|
|
||||||
*/
|
|
||||||
TerminalEditor::TerminalEditor(QETElementEditor* editor, QWidget* parent):
|
|
||||||
ElementItemEditor(editor, parent) {
|
|
||||||
m_part = nullptr;
|
|
||||||
m_terminals.clear();
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::TerminalEditor
|
|
||||||
Constructeur
|
|
||||||
@param editor :
|
|
||||||
L'editeur d'element concerne
|
|
||||||
@param terms :
|
|
||||||
La borne a editer
|
|
||||||
@param parent :
|
|
||||||
QWidget parent de ce widget
|
|
||||||
*/
|
|
||||||
TerminalEditor::TerminalEditor(
|
|
||||||
QETElementEditor *editor,
|
|
||||||
QList<PartTerminal *> &terms,
|
|
||||||
QWidget *parent) :
|
|
||||||
ElementItemEditor(editor, parent),
|
|
||||||
m_terminals(terms),
|
|
||||||
m_part(terms.first()) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::init
|
|
||||||
*/
|
|
||||||
void TerminalEditor::init()
|
|
||||||
{
|
|
||||||
qle_x = new QDoubleSpinBox();
|
|
||||||
qle_y = new QDoubleSpinBox();
|
|
||||||
name = new QLineEdit();
|
|
||||||
|
|
||||||
qle_x -> setRange(-5000, 5000);
|
|
||||||
qle_y -> setRange(-5000, 5000);
|
|
||||||
|
|
||||||
orientation = new QComboBox();
|
|
||||||
orientation -> addItem(QET::Icons::North, tr("Nord"), Qet::North);
|
|
||||||
orientation -> addItem(QET::Icons::East, tr("Est"), Qet::East);
|
|
||||||
orientation -> addItem(QET::Icons::South, tr("Sud"), Qet::South);
|
|
||||||
orientation -> addItem(QET::Icons::West, tr("Ouest"), Qet::West);
|
|
||||||
|
|
||||||
QVBoxLayout *main_layout = new QVBoxLayout();
|
|
||||||
main_layout -> addWidget(new QLabel(tr("Position : ")));
|
|
||||||
|
|
||||||
QHBoxLayout *position = new QHBoxLayout();
|
|
||||||
position -> addWidget(new QLabel(tr("x : ")));
|
|
||||||
position -> addWidget(qle_x );
|
|
||||||
position -> addWidget(new QLabel(tr("y : ")));
|
|
||||||
position -> addWidget(qle_y );
|
|
||||||
main_layout -> addLayout(position);
|
|
||||||
|
|
||||||
QHBoxLayout *ori = new QHBoxLayout();
|
|
||||||
ori -> addWidget(new QLabel(tr("Orientation : ")));
|
|
||||||
ori -> addWidget(orientation );
|
|
||||||
main_layout -> addLayout(ori);
|
|
||||||
|
|
||||||
QHBoxLayout *lay_name = new QHBoxLayout();
|
|
||||||
lay_name -> addWidget(new QLabel(tr("Name : ")));
|
|
||||||
lay_name -> addWidget(name);
|
|
||||||
main_layout -> addLayout(lay_name);
|
|
||||||
|
|
||||||
main_layout -> addStretch();
|
|
||||||
setLayout(main_layout);
|
|
||||||
|
|
||||||
activeConnections(true);
|
|
||||||
updateForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::~TerminalEditor
|
|
||||||
Destructeur
|
|
||||||
*/
|
|
||||||
TerminalEditor::~TerminalEditor()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Permet de specifier a cet editeur quelle primitive il doit editer. A noter
|
|
||||||
qu'un editeur peut accepter ou refuser d'editer une primitive.
|
|
||||||
L'editeur de borne acceptera d'editer la primitive new_part s'il s'agit d'un
|
|
||||||
objet de la classe PartTerminal.
|
|
||||||
@param new_part Nouvelle primitive a editer
|
|
||||||
@return true si l'editeur a accepter d'editer la primitive, false sinon
|
|
||||||
*/
|
|
||||||
bool TerminalEditor::setPart(CustomElementPart* new_part) {
|
|
||||||
m_terminals.clear();
|
|
||||||
if (!new_part) {
|
|
||||||
if (m_part) {
|
|
||||||
disconnect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
|
||||||
}
|
|
||||||
m_part = nullptr;
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
if (PartTerminal *part_terminal = static_cast<PartTerminal *>(new_part)) {
|
|
||||||
if(m_part == part_terminal) return true;
|
|
||||||
if (m_part) {
|
|
||||||
disconnect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
|
||||||
}
|
|
||||||
m_part = part_terminal;
|
|
||||||
updateForm();
|
|
||||||
connect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TerminalEditor::setParts(QList<CustomElementPart *> parts) {
|
|
||||||
if (parts.isEmpty()) {
|
|
||||||
m_terminals.clear();
|
|
||||||
if (m_part) {
|
|
||||||
disconnect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
|
||||||
}
|
|
||||||
m_part = nullptr;
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PartTerminal *part_terminal = static_cast<PartTerminal *>(parts.first())) {
|
|
||||||
if (m_part) {
|
|
||||||
disconnect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
|
||||||
}
|
|
||||||
m_part = part_terminal;
|
|
||||||
m_terminals.clear();
|
|
||||||
m_terminals.append(part_terminal);
|
|
||||||
for (int i=1; i < parts.length(); i++) {
|
|
||||||
m_terminals.append(static_cast<PartTerminal*>(parts[i]));
|
|
||||||
}
|
|
||||||
updateForm();
|
|
||||||
connect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@return la primitive actuellement editee, ou 0 si ce widget n'en edite pas
|
|
||||||
*/
|
|
||||||
CustomElementPart *TerminalEditor::currentPart() const
|
|
||||||
{
|
|
||||||
return(m_part);
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<CustomElementPart*> TerminalEditor::currentParts() const
|
|
||||||
{
|
|
||||||
QList<CustomElementPart*> parts;
|
|
||||||
for (auto term: m_terminals) {
|
|
||||||
parts.append(static_cast<CustomElementPart*>(term));
|
|
||||||
}
|
|
||||||
return parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Met a jour l'orientation de la borne et cree un objet d'annulation
|
|
||||||
void TerminalEditor::updateTerminalO()
|
|
||||||
{
|
|
||||||
if (m_locked) return;
|
|
||||||
m_locked = true;
|
|
||||||
QVariant var(orientation -> itemData(orientation -> currentIndex()));
|
|
||||||
|
|
||||||
for (int i=0; i < m_terminals.length(); i++) {
|
|
||||||
PartTerminal* term = m_terminals[i];
|
|
||||||
if (var != term->property("orientation"))
|
|
||||||
{
|
|
||||||
QPropertyUndoCommand *undo = new QPropertyUndoCommand(term, "orientation", term->property("orientation"), var);
|
|
||||||
undo->setText(tr("Modifier l'orientation d'une borne"));
|
|
||||||
undoStack().push(undo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_locked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::updateXPos
|
|
||||||
*/
|
|
||||||
void TerminalEditor::updateXPos()
|
|
||||||
{
|
|
||||||
if (m_locked) return;
|
|
||||||
m_locked = true;
|
|
||||||
QPointF new_pos(qle_x->value(), 0);
|
|
||||||
|
|
||||||
for (int i=0; i < m_terminals.length(); i++) {
|
|
||||||
PartTerminal* term = m_terminals[i];
|
|
||||||
new_pos.setY(term->pos().y()); // change only x value
|
|
||||||
if (term->pos() != new_pos) {
|
|
||||||
QPropertyUndoCommand *undo = new QPropertyUndoCommand(term, "pos", term->property("pos"), new_pos);
|
|
||||||
undo->setText(tr("Déplacer une borne"));
|
|
||||||
undo->enableAnimation();
|
|
||||||
undoStack().push(undo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_locked=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::updateYPos
|
|
||||||
*/
|
|
||||||
void TerminalEditor::updateYPos()
|
|
||||||
{
|
|
||||||
if (m_locked) return;
|
|
||||||
m_locked = true;
|
|
||||||
QPointF new_pos(0, qle_y->value()); // change only y value
|
|
||||||
|
|
||||||
for (int i=0; i < m_terminals.length(); i++) {
|
|
||||||
PartTerminal* term = m_terminals[i];
|
|
||||||
new_pos.setX(term->pos().x());
|
|
||||||
if (term->pos() != new_pos) {
|
|
||||||
QPropertyUndoCommand *undo = new QPropertyUndoCommand(term, "pos", term->property("pos"), new_pos);
|
|
||||||
undo->setText(tr("Déplacer une borne"));
|
|
||||||
undo->enableAnimation();
|
|
||||||
undoStack().push(undo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_locked=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief TerminalEditor::updateName
|
|
||||||
SLOT set name to Terminal
|
|
||||||
*/
|
|
||||||
void TerminalEditor::updateName() {
|
|
||||||
if (m_locked) return;
|
|
||||||
m_locked = true;
|
|
||||||
QVariant var(name->text());
|
|
||||||
|
|
||||||
for (int i=0; i < m_terminals.length(); i++) {
|
|
||||||
PartTerminal* term = m_terminals[i];
|
|
||||||
if (var != term->property("name"))
|
|
||||||
{
|
|
||||||
QPropertyUndoCommand *undo;
|
|
||||||
undo = new QPropertyUndoCommand(term,
|
|
||||||
"name",
|
|
||||||
term->property("name"),
|
|
||||||
var);
|
|
||||||
undo->setText(tr("Modifier le nom du terminal"));
|
|
||||||
undoStack().push(undo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_locked=false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// update Number and name, create cancel object
|
|
||||||
|
|
||||||
/**
|
|
||||||
Met a jour le formulaire d'edition
|
|
||||||
*/
|
|
||||||
void TerminalEditor::updateForm()
|
|
||||||
{
|
|
||||||
if (!m_part) return;
|
|
||||||
activeConnections(false);
|
|
||||||
qle_x -> setValue(m_part->property("x").toReal());
|
|
||||||
qle_y -> setValue(m_part->property("y").toReal());
|
|
||||||
orientation -> setCurrentIndex(orientation->findData(m_part->property("orientation")));
|
|
||||||
name -> setText(m_part->name());
|
|
||||||
activeConnections(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Active ou desactive les connexionx signaux/slots entre les widgets internes.
|
|
||||||
@param active true pour activer les connexions, false pour les desactiver
|
|
||||||
*/
|
|
||||||
void TerminalEditor::activeConnections(bool active) {
|
|
||||||
if (active) {
|
|
||||||
connect(qle_x,
|
|
||||||
&QDoubleSpinBox::editingFinished,
|
|
||||||
this, &TerminalEditor::updateXPos);
|
|
||||||
connect(qle_y,
|
|
||||||
&QDoubleSpinBox::editingFinished,
|
|
||||||
this, &TerminalEditor::updateYPos);
|
|
||||||
connect(orientation,
|
|
||||||
QOverload<int>::of(&QComboBox::activated),
|
|
||||||
this, &TerminalEditor::updateTerminalO);
|
|
||||||
connect(name, &QLineEdit::editingFinished,
|
|
||||||
this, &TerminalEditor::updateName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
disconnect(qle_x, &QDoubleSpinBox::editingFinished,
|
|
||||||
this, &TerminalEditor::updateXPos);
|
|
||||||
disconnect(qle_y, &QDoubleSpinBox::editingFinished,
|
|
||||||
this, &TerminalEditor::updateYPos);
|
|
||||||
disconnect(orientation, QOverload<int>::of(&QComboBox::activated),
|
|
||||||
this, &TerminalEditor::updateTerminalO);
|
|
||||||
disconnect(name, &QLineEdit::editingFinished,
|
|
||||||
this, &TerminalEditor::updateName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2006-2021 The QElectroTech Team
|
|
||||||
This file is part of QElectroTech.
|
|
||||||
|
|
||||||
QElectroTech is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
QElectroTech is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef TERMINAL_EDITOR_H
|
|
||||||
#define TERMINAL_EDITOR_H
|
|
||||||
|
|
||||||
#include "elementitemeditor.h"
|
|
||||||
|
|
||||||
#include <QLineEdit>
|
|
||||||
|
|
||||||
class PartTerminal;
|
|
||||||
class QDoubleSpinBox;
|
|
||||||
class QComboBox;
|
|
||||||
|
|
||||||
/**
|
|
||||||
@brief The TerminalEditor class
|
|
||||||
This class provides a widget to edit terminals within the element editor.
|
|
||||||
The class is capable to change the values of multiple parts of the same time.
|
|
||||||
The displayed values are from the first selected element
|
|
||||||
*/
|
|
||||||
class TerminalEditor : public ElementItemEditor {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
// Constructors, destructor
|
|
||||||
public:
|
|
||||||
TerminalEditor(
|
|
||||||
QETElementEditor *,
|
|
||||||
QList<PartTerminal *>& terms,
|
|
||||||
QWidget * = nullptr);
|
|
||||||
TerminalEditor(QETElementEditor *, QWidget * = nullptr);
|
|
||||||
~TerminalEditor() override;
|
|
||||||
private:
|
|
||||||
TerminalEditor(const TerminalEditor &);
|
|
||||||
void init();
|
|
||||||
|
|
||||||
// attributes
|
|
||||||
private:
|
|
||||||
QList<PartTerminal *> m_terminals;
|
|
||||||
PartTerminal *m_part{nullptr};
|
|
||||||
QDoubleSpinBox *qle_x, *qle_y;
|
|
||||||
QComboBox *orientation;
|
|
||||||
QLineEdit *name;
|
|
||||||
bool m_locked{false};
|
|
||||||
|
|
||||||
// methods
|
|
||||||
public:
|
|
||||||
bool setPart(CustomElementPart *) override;
|
|
||||||
bool setParts(QList<CustomElementPart *> parts) override;
|
|
||||||
CustomElementPart *currentPart() const override;
|
|
||||||
QList<CustomElementPart*> currentParts() const override;
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void updateTerminalO();
|
|
||||||
void updateXPos();
|
|
||||||
void updateYPos();
|
|
||||||
void updateName();
|
|
||||||
void updateForm() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void activeConnections(bool);
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -24,7 +24,8 @@
|
|||||||
#include "../../qetinformation.h"
|
#include "../../qetinformation.h"
|
||||||
#include "../../ui/alignmenttextdialog.h"
|
#include "../../ui/alignmenttextdialog.h"
|
||||||
#include "../../ui/compositetexteditdialog.h"
|
#include "../../ui/compositetexteditdialog.h"
|
||||||
#include "../qetelementeditor.h"
|
#include "../ui/qetelementeditor.h"
|
||||||
|
#include "../elementscene.h"
|
||||||
#include "ui_dynamictextfieldeditor.h"
|
#include "ui_dynamictextfieldeditor.h"
|
||||||
|
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
@@ -224,9 +225,9 @@ void DynamicTextFieldEditor::fillInfoComboBox()
|
|||||||
ui -> m_elmt_info_cb -> clear();
|
ui -> m_elmt_info_cb -> clear();
|
||||||
|
|
||||||
QStringList strl;
|
QStringList strl;
|
||||||
QString type = elementEditor() -> elementScene() -> elementType();
|
auto type = elementEditor()->elementScene()->elementData().m_type;
|
||||||
|
|
||||||
if(type.contains("report")) {
|
if(type & ElementData::AllReport) {
|
||||||
strl = QETInformation::folioReportInfoKeys();
|
strl = QETInformation::folioReportInfoKeys();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -332,8 +333,8 @@ void DynamicTextFieldEditor::on_m_elmt_info_cb_activated(const QString &arg1) {
|
|||||||
QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_parts[i], "infoName", m_parts[i] -> infoName(), info);
|
QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_parts[i], "infoName", m_parts[i] -> infoName(), info);
|
||||||
undo->setText(tr("Modifier l'information d'un texte"));
|
undo->setText(tr("Modifier l'information d'un texte"));
|
||||||
undoStack().push(undo);
|
undoStack().push(undo);
|
||||||
m_parts[i] -> setPlainText(
|
m_parts[i]->setPlainText(
|
||||||
elementEditor() -> elementScene() -> elementInformation().value(m_parts[i] -> infoName()).toString());
|
elementEditor()->elementScene()->elementData().m_informations.value(m_parts[i] -> infoName()).toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2006-2021 The QElectroTech Team
|
Copyright 2006-2021 The QElectroTech Team
|
||||||
This file is part of QElectroTech.
|
This file is part of QElectroTech.
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "../../qetapp.h"
|
#include "../../qetapp.h"
|
||||||
#include "../../qetinformation.h"
|
#include "../../qetinformation.h"
|
||||||
#include "ui_elementpropertieseditorwidget.h"
|
#include "ui_elementpropertieseditorwidget.h"
|
||||||
|
#include "../../qetinformation.h"
|
||||||
|
|
||||||
#include <QItemDelegate>
|
#include <QItemDelegate>
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ class EditorDelegate : public QItemDelegate
|
|||||||
|
|
||||||
QWidget* createEditor(QWidget *parent,
|
QWidget* createEditor(QWidget *parent,
|
||||||
const QStyleOptionViewItem &option,
|
const QStyleOptionViewItem &option,
|
||||||
const QModelIndex &index) const
|
const QModelIndex &index) const override
|
||||||
{
|
{
|
||||||
if(index.column() == 1)
|
if(index.column() == 1)
|
||||||
{
|
{
|
||||||
@@ -50,23 +51,14 @@ class EditorDelegate : public QItemDelegate
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief ElementPropertiesEditorWidget::ElementPropertiesEditorWidget
|
* @brief ElementPropertiesEditorWidget::ElementPropertiesEditorWidget
|
||||||
Default constructor
|
* @param data
|
||||||
@param basic_type : QString of the drawed element
|
* @param parent
|
||||||
@param kind_info : DiagramContext to store kindInfo of drawed element
|
*/
|
||||||
@param elmt_info : the information of element (label, manufacturer etc...]
|
ElementPropertiesEditorWidget::ElementPropertiesEditorWidget(ElementData data, QWidget *parent) :
|
||||||
@param parent : parent widget
|
|
||||||
*/
|
|
||||||
ElementPropertiesEditorWidget::ElementPropertiesEditorWidget(
|
|
||||||
QString &basic_type,
|
|
||||||
DiagramContext &kind_info,
|
|
||||||
DiagramContext &elmt_info,
|
|
||||||
QWidget *parent) :
|
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::ElementPropertiesEditorWidget),
|
ui(new Ui::ElementPropertiesEditorWidget),
|
||||||
m_basic_type(basic_type),
|
m_data(data)
|
||||||
m_kind_info (kind_info),
|
|
||||||
m_elmt_info (elmt_info)
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setUpInterface();
|
setUpInterface();
|
||||||
@@ -90,22 +82,29 @@ void ElementPropertiesEditorWidget::upDateInterface()
|
|||||||
{
|
{
|
||||||
ui->m_base_type_cb->setCurrentIndex(
|
ui->m_base_type_cb->setCurrentIndex(
|
||||||
ui->m_base_type_cb->findData(
|
ui->m_base_type_cb->findData(
|
||||||
QVariant(m_basic_type)));
|
m_data.m_type));
|
||||||
|
|
||||||
if (m_basic_type == "slave")
|
if (m_data.m_type == ElementData::Slave)
|
||||||
{
|
{
|
||||||
ui->m_state_cb->setCurrentIndex(
|
ui->m_state_cb->setCurrentIndex(
|
||||||
ui->m_state_cb->findData(
|
ui->m_state_cb->findData(
|
||||||
m_kind_info["state"].toString()));
|
m_data.m_slave_state));
|
||||||
ui->m_type_cb->setCurrentIndex (
|
ui->m_type_cb->setCurrentIndex (
|
||||||
ui->m_type_cb->findData(
|
ui->m_type_cb->findData(
|
||||||
m_kind_info["type"].toString()));
|
m_data.m_slave_type));
|
||||||
ui->m_number_ctc->setValue(m_kind_info["number"].toInt());
|
ui->m_number_ctc->setValue(m_data.m_contact_count);
|
||||||
}
|
}
|
||||||
else if (m_basic_type == "master") {
|
else if (m_data.m_type == ElementData::Master) {
|
||||||
ui->m_master_type_cb->setCurrentIndex(
|
ui->m_master_type_cb->setCurrentIndex(
|
||||||
ui->m_master_type_cb->findData (
|
ui->m_master_type_cb->findData (
|
||||||
m_kind_info["type"]));
|
m_data.m_master_type));
|
||||||
|
} else if (m_data.m_type == ElementData::Terminale) {
|
||||||
|
ui->m_terminal_type_cb->setCurrentIndex(
|
||||||
|
ui->m_terminal_type_cb->findData(
|
||||||
|
m_data.m_terminal_type));
|
||||||
|
ui->m_terminal_func_cb->setCurrentIndex(
|
||||||
|
ui->m_terminal_func_cb->findData(
|
||||||
|
m_data.m_terminal_function));
|
||||||
}
|
}
|
||||||
|
|
||||||
on_m_base_type_cb_currentIndexChanged(ui->m_base_type_cb->currentIndex());
|
on_m_base_type_cb_currentIndexChanged(ui->m_base_type_cb->currentIndex());
|
||||||
@@ -117,33 +116,39 @@ void ElementPropertiesEditorWidget::upDateInterface()
|
|||||||
void ElementPropertiesEditorWidget::setUpInterface()
|
void ElementPropertiesEditorWidget::setUpInterface()
|
||||||
{
|
{
|
||||||
// Type combo box
|
// Type combo box
|
||||||
ui->m_base_type_cb->addItem (tr("Simple"), QVariant("simple"));
|
ui->m_base_type_cb->addItem (tr("Simple"), ElementData::Simple);
|
||||||
ui->m_base_type_cb->addItem (tr("Maître"), QVariant("master"));
|
ui->m_base_type_cb->addItem (tr("Maître"), ElementData::Master);
|
||||||
ui->m_base_type_cb->addItem (tr("Esclave"), QVariant("slave"));
|
ui->m_base_type_cb->addItem (tr("Esclave"), ElementData::Slave);
|
||||||
ui->m_base_type_cb->addItem (tr("Renvoi de folio suivant"),
|
ui->m_base_type_cb->addItem (tr("Renvoi de folio suivant"), ElementData::NextReport);
|
||||||
QVariant("next_report"));
|
ui->m_base_type_cb->addItem (tr("Renvoi de folio précédent"), ElementData::PreviousReport);
|
||||||
ui->m_base_type_cb->addItem (tr("Renvoi de folio précédent"),
|
ui->m_base_type_cb->addItem (tr("Bornier"), ElementData::Terminale);
|
||||||
QVariant("previous_report"));
|
|
||||||
ui->m_base_type_cb->addItem (tr("Bornier"), QVariant("terminal"));
|
|
||||||
|
|
||||||
// Slave option
|
// Slave option
|
||||||
ui->m_state_cb->addItem(tr("Normalement ouvert"),QVariant("NO"));
|
ui->m_state_cb->addItem(tr("Normalement ouvert"), ElementData::NO);
|
||||||
ui->m_state_cb->addItem(tr("Normalement fermé"), QVariant("NC"));
|
ui->m_state_cb->addItem(tr("Normalement fermé"), ElementData::NC);
|
||||||
ui->m_state_cb->addItem(tr("Inverseur"), QVariant("SW"));
|
ui->m_state_cb->addItem(tr("Inverseur"), ElementData::SW);
|
||||||
ui->m_type_cb->addItem(tr("Simple"), QVariant("simple"));
|
ui->m_type_cb->addItem(tr("Simple"), ElementData::SSimple);
|
||||||
ui->m_type_cb->addItem(tr("Puissance"), QVariant("power"));
|
ui->m_type_cb->addItem(tr("Puissance"), ElementData::Power);
|
||||||
ui->m_type_cb->addItem(tr("Temporisé travail"), QVariant("delayOn"));
|
ui->m_type_cb->addItem(tr("Temporisé travail"), ElementData::DelayOn);
|
||||||
ui->m_type_cb->addItem(tr("Temporisé repos"), QVariant("delayOff"));
|
ui->m_type_cb->addItem(tr("Temporisé repos"), ElementData::DelayOff);
|
||||||
ui->m_type_cb->addItem(tr("Temporisé travail & repos"),
|
ui->m_type_cb->addItem(tr("Temporisé travail & repos"), ElementData::delayOnOff);
|
||||||
QVariant("delayOnOff"));
|
|
||||||
|
|
||||||
//Master option
|
//Master option
|
||||||
ui->m_master_type_cb->addItem(tr("Bobine"), QVariant("coil"));
|
ui->m_master_type_cb->addItem(tr("Bobine"), ElementData::Coil);
|
||||||
ui->m_master_type_cb->addItem(tr("Organe de protection"),
|
ui->m_master_type_cb->addItem(tr("Organe de protection"), ElementData::Protection);
|
||||||
QVariant("protection"));
|
ui->m_master_type_cb->addItem(tr("Commutateur / bouton"), ElementData::Commutator);
|
||||||
ui->m_master_type_cb->addItem(tr("Commutateur / bouton"),
|
|
||||||
QVariant("commutator"));
|
//Terminal option
|
||||||
|
ui->m_terminal_type_cb->addItem(tr("Générique"), ElementData::TTGeneric);
|
||||||
|
ui->m_terminal_type_cb->addItem(tr("Fusible"), ElementData::Fuse);
|
||||||
|
ui->m_terminal_type_cb->addItem(tr("Séctionnable"), ElementData::Sectional);
|
||||||
|
ui->m_terminal_type_cb->addItem(tr("Diode"), ElementData::Diode);
|
||||||
|
|
||||||
|
ui->m_terminal_func_cb->addItem(tr("Générique"), ElementData::TFGeneric);
|
||||||
|
ui->m_terminal_func_cb->addItem(tr("Phase"), ElementData::Phase);
|
||||||
|
ui->m_terminal_func_cb->addItem(tr("Neutre"), ElementData::Neutral);
|
||||||
|
ui->m_terminal_func_cb->addItem(tr("Terre"), ElementData::PE);
|
||||||
|
|
||||||
//Disable the edition of the first column of the information tree
|
//Disable the edition of the first column of the information tree
|
||||||
//by this little workaround
|
//by this little workaround
|
||||||
ui->m_tree->setItemDelegate(new EditorDelegate(this));
|
ui->m_tree->setItemDelegate(new EditorDelegate(this));
|
||||||
@@ -153,21 +158,28 @@ void ElementPropertiesEditorWidget::setUpInterface()
|
|||||||
|
|
||||||
void ElementPropertiesEditorWidget::updateTree()
|
void ElementPropertiesEditorWidget::updateTree()
|
||||||
{
|
{
|
||||||
QString type = ui->m_base_type_cb->itemData(
|
auto type_ = ui->m_base_type_cb->currentData().value<ElementData::Type>();
|
||||||
ui->m_base_type_cb->currentIndex()).toString();
|
|
||||||
|
switch (type_) {
|
||||||
if (type == "master")
|
case ElementData::Simple:
|
||||||
ui->m_tree->setEnabled(true);
|
ui->m_tree->setEnabled(true);
|
||||||
else if (type == "slave")
|
break;
|
||||||
ui->m_tree->setDisabled(true);
|
case ElementData::NextReport:
|
||||||
else if (type == "simple")
|
ui->m_tree->setDisabled(true);
|
||||||
ui->m_tree->setEnabled(true);
|
break;
|
||||||
else if (type == "next_report")
|
case ElementData::PreviousReport:
|
||||||
ui->m_tree->setDisabled(true);
|
ui->m_tree->setDisabled(true);
|
||||||
else if (type == "previous_report")
|
break;
|
||||||
ui->m_tree->setDisabled(true);
|
case ElementData::Master:
|
||||||
else if (type == "terminal")
|
ui->m_tree->setEnabled(true);
|
||||||
ui->m_tree->setEnabled(true);
|
break;
|
||||||
|
case ElementData::Slave:
|
||||||
|
ui->m_tree->setDisabled(true);
|
||||||
|
break;
|
||||||
|
case ElementData::Terminale:
|
||||||
|
ui->m_tree->setEnabled(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,20 +187,16 @@ void ElementPropertiesEditorWidget::updateTree()
|
|||||||
Create QTreeWidgetItem of the tree widget and populate it
|
Create QTreeWidgetItem of the tree widget and populate it
|
||||||
*/
|
*/
|
||||||
void ElementPropertiesEditorWidget::populateTree()
|
void ElementPropertiesEditorWidget::populateTree()
|
||||||
{
|
{
|
||||||
QStringList keys{"label", "plant", "comment", "description",
|
const auto keys = QETInformation::elementEditorElementInfoKeys();
|
||||||
"designation", "manufacturer",
|
|
||||||
"manufacturer_reference", "supplier", "quantity",
|
|
||||||
"unity", "machine_manufacturer_reference"};
|
|
||||||
|
|
||||||
for(const QString& key : keys)
|
for(const QString& key : keys)
|
||||||
{
|
{
|
||||||
QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_tree);
|
QTreeWidgetItem *qtwi = new QTreeWidgetItem(ui->m_tree);
|
||||||
qtwi->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
qtwi->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
|
||||||
qtwi->setData(0, Qt::DisplayRole,
|
qtwi->setData(0, Qt::DisplayRole,
|
||||||
QETInformation::translatedInfoKey(key));
|
QETInformation::translatedInfoKey(key));
|
||||||
qtwi->setData(0, Qt::UserRole, key);
|
qtwi->setData(0, Qt::UserRole, key);
|
||||||
qtwi->setText(1, m_elmt_info.value(key).toString());
|
qtwi->setText(1, m_data.m_informations.value(key).toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,23 +206,21 @@ void ElementPropertiesEditorWidget::populateTree()
|
|||||||
*/
|
*/
|
||||||
void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
||||||
{
|
{
|
||||||
m_basic_type = ui->m_base_type_cb->itemData(
|
m_data.m_type = ui->m_base_type_cb->currentData().value<ElementData::Type>();
|
||||||
ui->m_base_type_cb->currentIndex()).toString();
|
|
||||||
if (m_basic_type == "slave")
|
if (m_data.m_type == ElementData::Slave)
|
||||||
{
|
{
|
||||||
m_kind_info.addValue("state",
|
m_data.m_slave_state = ui->m_state_cb->currentData().value<ElementData::SlaveState>();
|
||||||
ui->m_state_cb->itemData(
|
m_data.m_slave_type = ui->m_type_cb->currentData().value<ElementData::SlaveType>();
|
||||||
ui->m_state_cb->currentIndex()));
|
m_data.m_contact_count = ui->m_number_ctc->value();
|
||||||
m_kind_info.addValue("type",
|
|
||||||
ui->m_type_cb->itemData(
|
|
||||||
ui->m_type_cb->currentIndex()));
|
|
||||||
m_kind_info.addValue("number",
|
|
||||||
QVariant(ui->m_number_ctc->value()));
|
|
||||||
}
|
}
|
||||||
else if(m_basic_type == "master") {
|
else if (m_data.m_type == ElementData::Master) {
|
||||||
m_kind_info.addValue("type",
|
m_data.m_master_type = ui->m_master_type_cb->currentData().value<ElementData::MasterType>();
|
||||||
ui->m_master_type_cb->itemData(
|
}
|
||||||
ui->m_master_type_cb->currentIndex()));
|
else if (m_data.m_type == ElementData::Terminale)
|
||||||
|
{
|
||||||
|
m_data.m_terminal_type = ui->m_terminal_type_cb->currentData().value<ElementData::TerminalType>();
|
||||||
|
m_data.m_terminal_function = ui->m_terminal_func_cb->currentData().value<ElementData::TerminalFunction>();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (QTreeWidgetItem *qtwi : ui->m_tree->invisibleRootItem()->takeChildren())
|
for (QTreeWidgetItem *qtwi : ui->m_tree->invisibleRootItem()->takeChildren())
|
||||||
@@ -224,8 +230,8 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
|||||||
txt.remove("\r");
|
txt.remove("\r");
|
||||||
txt.remove("\n");
|
txt.remove("\n");
|
||||||
|
|
||||||
m_elmt_info.addValue(qtwi->data(0, Qt::UserRole).toString(),
|
m_data.m_informations.addValue(qtwi->data(0, Qt::UserRole).toString(),
|
||||||
txt);
|
txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->close();
|
this->close();
|
||||||
@@ -235,18 +241,23 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
|||||||
@brief ElementPropertiesEditorWidget::on_m_base_type_cb_currentIndexChanged
|
@brief ElementPropertiesEditorWidget::on_m_base_type_cb_currentIndexChanged
|
||||||
@param index : Action when combo-box base type index change
|
@param index : Action when combo-box base type index change
|
||||||
*/
|
*/
|
||||||
void ElementPropertiesEditorWidget::on_m_base_type_cb_currentIndexChanged(
|
void ElementPropertiesEditorWidget::on_m_base_type_cb_currentIndexChanged(int index)
|
||||||
int index)
|
|
||||||
{
|
{
|
||||||
bool slave = false , master = false;
|
bool slave = false , master = false, terminal = false;
|
||||||
|
|
||||||
if (ui->m_base_type_cb->itemData(index).toString() == "slave")
|
auto type_ = ui->m_base_type_cb->itemData(index).value<ElementData::Type>();
|
||||||
|
if (type_ == ElementData::Slave)
|
||||||
slave = true;
|
slave = true;
|
||||||
else if (ui->m_base_type_cb->itemData(index).toString() == "master")
|
else if (type_ == ElementData::Master)
|
||||||
master = true;
|
master = true;
|
||||||
|
else if (type_ == ElementData::Terminale)
|
||||||
|
terminal = true;
|
||||||
|
|
||||||
ui->m_slave_gb->setVisible(slave);
|
ui->m_slave_gb->setVisible(slave);
|
||||||
ui->m_master_gb->setVisible(master);
|
ui->m_master_gb->setVisible(master);
|
||||||
|
ui->m_terminal_gb->setVisible(terminal);
|
||||||
|
ui->tabWidget->setTabVisible(1,
|
||||||
|
(type_ == ElementData::Simple ||
|
||||||
|
type_ == ElementData::Master));
|
||||||
updateTree();
|
updateTree();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define ELEMENTPROPERTIESEDITORWIDGET_H
|
#define ELEMENTPROPERTIESEDITORWIDGET_H
|
||||||
|
|
||||||
#include "../../diagramcontext.h"
|
#include "../../diagramcontext.h"
|
||||||
|
#include "../../properties/elementdata.h"
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
@@ -38,12 +39,13 @@ class ElementPropertiesEditorWidget : public QDialog
|
|||||||
|
|
||||||
//METHODS
|
//METHODS
|
||||||
public:
|
public:
|
||||||
explicit ElementPropertiesEditorWidget(QString &basic_type, DiagramContext &kind_info, DiagramContext &elmt_info, QWidget *parent = nullptr);
|
explicit ElementPropertiesEditorWidget(ElementData data, QWidget *parent = nullptr);
|
||||||
~ElementPropertiesEditorWidget() override;
|
~ElementPropertiesEditorWidget() override;
|
||||||
|
|
||||||
void upDateInterface();
|
ElementData editedData() {return m_data;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void upDateInterface();
|
||||||
void setUpInterface();
|
void setUpInterface();
|
||||||
void updateTree();
|
void updateTree();
|
||||||
void populateTree();
|
void populateTree();
|
||||||
@@ -56,9 +58,7 @@ class ElementPropertiesEditorWidget : public QDialog
|
|||||||
//ATTRIBUTES
|
//ATTRIBUTES
|
||||||
private:
|
private:
|
||||||
Ui::ElementPropertiesEditorWidget *ui;
|
Ui::ElementPropertiesEditorWidget *ui;
|
||||||
QString &m_basic_type;
|
ElementData m_data;
|
||||||
DiagramContext &m_kind_info,
|
|
||||||
&m_elmt_info;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ELEMENTPROPERTIESEDITORWIDGET_H
|
#endif // ELEMENTPROPERTIESEDITORWIDGET_H
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>450</width>
|
<width>527</width>
|
||||||
<height>321</height>
|
<height>442</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -107,6 +107,35 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="m_terminal_gb">
|
||||||
|
<property name="title">
|
||||||
|
<string>Élément bornier</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Fonction</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="m_terminal_type_cb"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="m_terminal_func_cb"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 The QElectroTech Team
|
||||||
|
This file is part of QElectroTech.
|
||||||
|
|
||||||
|
QElectroTech is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
QElectroTech is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef QETELEMENTEDITOR_H
|
||||||
|
#define QETELEMENTEDITOR_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include "../../ElementsCollection/elementslocation.h"
|
||||||
|
|
||||||
|
class ElementScene;
|
||||||
|
class QActionGroup;
|
||||||
|
class ElementItemEditor;
|
||||||
|
class ElementView;
|
||||||
|
class QListWidget;
|
||||||
|
class QStackedWidget;
|
||||||
|
class QLabel;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class QETElementEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QETElementEditor : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
signals:
|
||||||
|
void saveToLocation(ElementsLocation loc);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit QETElementEditor(QWidget *parent = nullptr);
|
||||||
|
~QETElementEditor() override;
|
||||||
|
|
||||||
|
void contextMenu(QPoint p, QList<QAction *> actions = QList<QAction *>());
|
||||||
|
void setNames(const NamesList &name_list);
|
||||||
|
void setLocation(const ElementsLocation &location);
|
||||||
|
ElementsLocation location() const;
|
||||||
|
void setFileName(const QString &file_name);
|
||||||
|
QString fileName() const;
|
||||||
|
void setReadOnly(bool ro);
|
||||||
|
bool isReadOnly() const;
|
||||||
|
void fromFile(const QString &filepath);
|
||||||
|
bool toFile(const QString &filepath);
|
||||||
|
void fromLocation(const ElementsLocation &location);
|
||||||
|
bool toLocation(const ElementsLocation &location);
|
||||||
|
bool isEditing(const ElementsLocation &location);
|
||||||
|
bool isEditing(const QString &filepath);
|
||||||
|
ElementScene *elementScene() const;
|
||||||
|
ElementView *elementView() const;
|
||||||
|
static QPointF pasteOffset();
|
||||||
|
static QString getOpenElementFileName(QWidget *parent = nullptr, const QString &dir = QString());
|
||||||
|
void updateTitle();
|
||||||
|
void fillPartsList();
|
||||||
|
void UncheckAddPrimitive();
|
||||||
|
void updateCurrentPartEditor();
|
||||||
|
void updateInformations();
|
||||||
|
void updatePartsList();
|
||||||
|
void updateSelectionFromPartsList();
|
||||||
|
void openElement(const QString &filepath);
|
||||||
|
bool checkElement();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool event(QEvent *event) override;
|
||||||
|
void closeEvent(QCloseEvent *) override;
|
||||||
|
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
bool on_m_save_action_triggered();
|
||||||
|
bool on_m_save_as_action_triggered();
|
||||||
|
void on_m_select_all_act_triggered();
|
||||||
|
void on_m_edit_element_properties_action_triggered();
|
||||||
|
void on_m_new_action_triggered();
|
||||||
|
void on_m_open_action_triggered();
|
||||||
|
void on_m_open_from_file_action_triggered();
|
||||||
|
void on_m_open_dxf_action_triggered();
|
||||||
|
bool on_m_save_as_file_action_triggered();
|
||||||
|
void on_m_reload_action_triggered();
|
||||||
|
void on_m_quit_action_triggered();
|
||||||
|
void on_m_deselect_all_action_triggered();
|
||||||
|
void on_m_cut_action_triggered();
|
||||||
|
void on_m_copy_action_triggered();
|
||||||
|
void on_m_paste_action_triggered();
|
||||||
|
void on_m_paste_in_area_action_triggered();
|
||||||
|
void on_m_paste_from_file_action_triggered();
|
||||||
|
void on_m_paste_from_element_action_triggered();
|
||||||
|
void on_m_revert_selection_action_triggered();
|
||||||
|
void on_m_delete_action_triggered();
|
||||||
|
void on_m_edit_names_action_triggered();
|
||||||
|
void on_m_edit_author_action_triggered();
|
||||||
|
void on_m_zoom_in_action_triggered();
|
||||||
|
void on_m_zoom_out_action_triggered();
|
||||||
|
void on_m_zoom_fit_best_action_triggered();
|
||||||
|
void on_m_zoom_original_action_triggered();
|
||||||
|
void on_m_about_qet_action_triggered();
|
||||||
|
void on_m_online_manual_triggered();
|
||||||
|
void on_m_youtube_action_triggered();
|
||||||
|
void on_m_donate_action_triggered();
|
||||||
|
void on_m_about_qt_action_triggered();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool canClose();
|
||||||
|
void readSettings();
|
||||||
|
void writeSettings() const;
|
||||||
|
void setupActions();
|
||||||
|
void updateAction();
|
||||||
|
void setupConnection();
|
||||||
|
void initGui();
|
||||||
|
QWidget *clearToolsDock();
|
||||||
|
void copyAndPasteXml(const QDomDocument &xml_document);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::QETElementEditor *ui;
|
||||||
|
|
||||||
|
bool
|
||||||
|
m_read_only = false,
|
||||||
|
m_opened_from_file = false,
|
||||||
|
m_first_activation = true;
|
||||||
|
|
||||||
|
ElementScene *m_elmt_scene = nullptr;
|
||||||
|
|
||||||
|
QActionGroup
|
||||||
|
*m_add_part_action_grp = nullptr,
|
||||||
|
*m_depth_action_group = nullptr;
|
||||||
|
|
||||||
|
QList<QAction *> m_context_menu_action_list;
|
||||||
|
|
||||||
|
QAction
|
||||||
|
*m_undo_action = nullptr,
|
||||||
|
*m_redo_action = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
/// Hash associating primitive names with their matching edition widget
|
||||||
|
QHash<QString, ElementItemEditor *> m_editors;
|
||||||
|
|
||||||
|
ElementsLocation m_location;
|
||||||
|
|
||||||
|
QString
|
||||||
|
m_file_name,
|
||||||
|
m_min_title;
|
||||||
|
|
||||||
|
ElementView *m_view = nullptr;
|
||||||
|
|
||||||
|
QListWidget *m_parts_list = nullptr;
|
||||||
|
|
||||||
|
QStackedWidget *m_tools_dock_stack = nullptr;
|
||||||
|
|
||||||
|
QLabel *m_default_informations = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QETELEMENTEDITOR_H
|
||||||
@@ -0,0 +1,496 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>QETElementEditor</class>
|
||||||
|
<widget class="QMainWindow" name="QETElementEditor">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>600</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>QElectroTech - Éditeur d'élément</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/qet.png</normaloff>:/ico/16x16/qet.png</iconset>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget"/>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>21</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="m_file_menu">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Fichier</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="m_new_action"/>
|
||||||
|
<addaction name="m_open_action"/>
|
||||||
|
<addaction name="m_open_from_file_action"/>
|
||||||
|
<addaction name="m_open_dxf_action"/>
|
||||||
|
<addaction name="m_save_action"/>
|
||||||
|
<addaction name="m_save_as_action"/>
|
||||||
|
<addaction name="m_save_as_file_action"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_reload_action"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_quit_action"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="m_edit_menu">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Édition</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="m_paste_from_menu">
|
||||||
|
<property name="title">
|
||||||
|
<string>Coller depuis...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-paste.png</normaloff>:/ico/16x16/edit-paste.png</iconset>
|
||||||
|
</property>
|
||||||
|
<addaction name="m_paste_from_file_action"/>
|
||||||
|
<addaction name="m_paste_from_element_action"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_select_all_act"/>
|
||||||
|
<addaction name="m_deselect_all_action"/>
|
||||||
|
<addaction name="m_revert_selection_action"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_cut_action"/>
|
||||||
|
<addaction name="m_copy_action"/>
|
||||||
|
<addaction name="m_paste_action"/>
|
||||||
|
<addaction name="m_paste_in_area_action"/>
|
||||||
|
<addaction name="m_paste_from_menu"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_delete_action"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_edit_names_action"/>
|
||||||
|
<addaction name="m_edit_author_action"/>
|
||||||
|
<addaction name="m_edit_element_properties_action"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="m_display_menu">
|
||||||
|
<property name="title">
|
||||||
|
<string>Afficha&ge</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="m_zoom_in_action"/>
|
||||||
|
<addaction name="m_zoom_out_action"/>
|
||||||
|
<addaction name="m_zoom_fit_best_action"/>
|
||||||
|
<addaction name="m_zoom_original_action"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menu_Aide">
|
||||||
|
<property name="title">
|
||||||
|
<string>&Aide</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="m_about_qet_action"/>
|
||||||
|
<addaction name="m_online_manual"/>
|
||||||
|
<addaction name="m_youtube_action"/>
|
||||||
|
<addaction name="m_donate_action"/>
|
||||||
|
<addaction name="m_about_qt_action"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="m_file_menu"/>
|
||||||
|
<addaction name="m_edit_menu"/>
|
||||||
|
<addaction name="m_display_menu"/>
|
||||||
|
<addaction name="menu_Aide"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QDockWidget" name="m_undo_dock">
|
||||||
|
<property name="allowedAreas">
|
||||||
|
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Annulations</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="dockWidgetArea">
|
||||||
|
<number>1</number>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QDockWidget" name="m_parts_dock">
|
||||||
|
<property name="allowedAreas">
|
||||||
|
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Parties</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="dockWidgetArea">
|
||||||
|
<number>2</number>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents_2"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QDockWidget" name="m_tools_dock">
|
||||||
|
<property name="allowedAreas">
|
||||||
|
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Informations</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="dockWidgetArea">
|
||||||
|
<number>1</number>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents_3"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="m_main_toolbar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Outils</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="m_new_action"/>
|
||||||
|
<addaction name="m_open_action"/>
|
||||||
|
<addaction name="m_save_action"/>
|
||||||
|
<addaction name="m_save_as_action"/>
|
||||||
|
<addaction name="m_reload_action"/>
|
||||||
|
<addaction name="m_delete_action"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="m_view_toolbar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Affichage</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="m_zoom_in_action"/>
|
||||||
|
<addaction name="m_zoom_out_action"/>
|
||||||
|
<addaction name="m_zoom_fit_best_action"/>
|
||||||
|
<addaction name="m_zoom_original_action"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="m_element_toolbar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Élément</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<addaction name="m_edit_names_action"/>
|
||||||
|
<addaction name="m_edit_element_properties_action"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="m_undo_toolbar">
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Annulation</string>
|
||||||
|
</property>
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<action name="m_select_all_act">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-select-all.png</normaloff>:/ico/16x16/edit-select-all.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Tout sélectionner</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_new_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/document-new.png</normaloff>:/ico/22x22/document-new.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Nouveau</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_open_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/folder-open.png</normaloff>:/ico/22x22/folder-open.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Ouvrir</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_open_from_file_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/folder-open.png</normaloff>:/ico/22x22/folder-open.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Ouvrir depuis un fichier</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_open_dxf_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/run-dxf.png</normaloff>:/ico/16x16/run-dxf.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Lancer le plugin convertisseur DXF</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_save_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/document-save.png</normaloff>:/ico/22x22/document-save.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Enregistrer</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_save_as_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/document-save-as.png</normaloff>:/ico/22x22/document-save-as.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Enregistrer sous</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_save_as_file_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/document-save.png</normaloff>:/ico/22x22/document-save.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Enregistrer dans un fichier</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_reload_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/view-refresh.png</normaloff>:/ico/22x22/view-refresh.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Recharger</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_quit_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/application-exit.png</normaloff>:/ico/16x16/application-exit.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Quitter</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_deselect_all_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-select-none.png</normaloff>:/ico/16x16/edit-select-none.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Désélectionner tout</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_cut_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-cut.png</normaloff>:/ico/16x16/edit-cut.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Co&uper</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_copy_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-copy.png</normaloff>:/ico/16x16/edit-copy.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Cop&ier</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_paste_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-paste.png</normaloff>:/ico/16x16/edit-paste.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>C&oller</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_paste_in_area_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-paste.png</normaloff>:/ico/16x16/edit-paste.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>C&oller dans la zone</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_paste_from_file_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/text-xml.png</normaloff>:/ico/16x16/text-xml.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Un fichier</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_paste_from_element_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/element.png</normaloff>:/ico/16x16/element.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Un élément</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_revert_selection_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/edit-select-invert.png</normaloff>:/ico/16x16/edit-select-invert.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Inverser la sélection</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_delete_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/edit-delete.png</normaloff>:/ico/22x22/edit-delete.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>&Supprimer</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_edit_names_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/names.png</normaloff>:/ico/22x22/names.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Éditer le nom et les traductions de l'élément</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_edit_author_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/preferences-desktop-user.png</normaloff>:/ico/16x16/preferences-desktop-user.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Éditer les informations sur l'auteur</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_edit_element_properties_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/element-edit.png</normaloff>:/ico/22x22/element-edit.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Éditer les propriétés de l'élément</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_zoom_in_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/zoom-in.png</normaloff>:/ico/22x22/zoom-in.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Zoom avant</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_zoom_out_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/zoom-out.png</normaloff>:/ico/22x22/zoom-out.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Zoom arrière</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_zoom_fit_best_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/zoom-fit-best.png</normaloff>:/ico/22x22/zoom-fit-best.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Zoom adapté</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_zoom_original_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/22x22/zoom-original.png</normaloff>:/ico/22x22/zoom-original.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pas de zoom</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_about_qet_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/qet.png</normaloff>:/ico/16x16/qet.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>À &propos de QElectroTech</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Affiche des informations sur QElectroTech</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_online_manual">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/help-contents.png</normaloff>:/ico/16x16/help-contents.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Manuel en ligne</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Lance le navigateur par défaut vers le manuel en ligne de QElectroTech</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_youtube_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/kdenlive-show-video.png</normaloff>:/ico/16x16/kdenlive-show-video.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Chaine Youtube</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Lance le navigateur par défaut vers la chaine Youtube de QElectroTech</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_donate_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/help-donate.png</normaloff>:/ico/16x16/help-donate.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Soutenir le projet par un don</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Soutenir le projet QElectroTech par un don</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="m_about_qt_action">
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../qelectrotech.qrc">
|
||||||
|
<normaloff>:/ico/16x16/qt.png</normaloff>:/ico/16x16/qt.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>À propos de &Qt</string>
|
||||||
|
</property>
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Affiche des informations sur la bibliothèque Qt</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../../../qelectrotech.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 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 "terminaleditor.h"
|
||||||
|
#include "ui_terminaleditor.h"
|
||||||
|
#include "../../qeticons.h"
|
||||||
|
#include "../../qet.h"
|
||||||
|
#include "../graphicspart/partterminal.h"
|
||||||
|
#include "../../QPropertyUndoCommand/qpropertyundocommand.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::TerminalEditor
|
||||||
|
* Default constructor
|
||||||
|
* @param editor : element editor of which this terminal editor belong
|
||||||
|
* @param parent : parent widget
|
||||||
|
*/
|
||||||
|
TerminalEditor::TerminalEditor(QETElementEditor *editor, QWidget *parent) :
|
||||||
|
ElementItemEditor(editor, parent),
|
||||||
|
ui(new Ui::TerminalEditor)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::~TerminalEditor
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
TerminalEditor::~TerminalEditor()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::updateForm
|
||||||
|
* Reimplemented from ElementItemEditor
|
||||||
|
* Update the content of this widget
|
||||||
|
*/
|
||||||
|
void TerminalEditor::updateForm()
|
||||||
|
{
|
||||||
|
if (!m_part) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeConnections(false);
|
||||||
|
|
||||||
|
ui->m_x_dsb->setValue(m_part->property("x").toReal());
|
||||||
|
ui->m_y_dsb->setValue(m_part->property("y").toReal());
|
||||||
|
ui->m_orientation_cb->setCurrentIndex(ui->m_orientation_cb->findData(m_part->property("orientation")));
|
||||||
|
ui->m_name_le->setText(m_part->name());
|
||||||
|
ui->m_type_cb->setCurrentIndex(ui->m_orientation_cb->findData(m_part->terminalType()));
|
||||||
|
|
||||||
|
activeConnections(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::setPart
|
||||||
|
* Set the part to edit.
|
||||||
|
* The part must be a PartTerminal, in other case return false.
|
||||||
|
* @param new_part : the part to edit
|
||||||
|
* @return true if the part can be edited.
|
||||||
|
*/
|
||||||
|
bool TerminalEditor::setPart(CustomElementPart *new_part)
|
||||||
|
{
|
||||||
|
if (m_part == new_part) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
activeChangeConnections(false);
|
||||||
|
|
||||||
|
if (!new_part)
|
||||||
|
{
|
||||||
|
m_part = nullptr;
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PartTerminal *part_terminal = dynamic_cast<PartTerminal *>(new_part))
|
||||||
|
{
|
||||||
|
m_part = part_terminal;
|
||||||
|
updateForm();
|
||||||
|
activeChangeConnections(true);
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::currentPart
|
||||||
|
* @return the current edited part
|
||||||
|
* or nullptr if there is no part or several part
|
||||||
|
* @see QList<CustomElementPart *> TerminalEditor::currentParts() const
|
||||||
|
*/
|
||||||
|
CustomElementPart *TerminalEditor::currentPart() const
|
||||||
|
{
|
||||||
|
return m_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::init
|
||||||
|
* Some init about this class
|
||||||
|
*/
|
||||||
|
void TerminalEditor::init()
|
||||||
|
{
|
||||||
|
ui->m_orientation_cb->addItem(QET::Icons::North, tr("Nord"), Qet::North);
|
||||||
|
ui->m_orientation_cb->addItem(QET::Icons::East, tr("Est"), Qet::East);
|
||||||
|
ui->m_orientation_cb->addItem(QET::Icons::South, tr("Sud"), Qet::South);
|
||||||
|
ui->m_orientation_cb->addItem(QET::Icons::West, tr("Ouest"), Qet::West);
|
||||||
|
|
||||||
|
ui->m_type_cb->addItem(tr("Générique"), TerminalData::Generic);
|
||||||
|
ui->m_type_cb->addItem(tr("Bornier intérieur"), TerminalData::Inner);
|
||||||
|
ui->m_type_cb->addItem(tr("Bornier extérieur"), TerminalData::Outer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::posEdited
|
||||||
|
*/
|
||||||
|
void TerminalEditor::posEdited()
|
||||||
|
{
|
||||||
|
if (m_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_locked = true;
|
||||||
|
|
||||||
|
QPointF new_pos(ui->m_x_dsb->value(),
|
||||||
|
ui->m_y_dsb->value());
|
||||||
|
|
||||||
|
if (m_part->pos() != new_pos)
|
||||||
|
{
|
||||||
|
auto undo = new QPropertyUndoCommand(m_part, "pos", m_part->property("pos"), new_pos);
|
||||||
|
undo->setText(tr("Déplacer une borne"));
|
||||||
|
undo->setAnimated(true, false);
|
||||||
|
undoStack().push(undo);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::orientationEdited
|
||||||
|
*/
|
||||||
|
void TerminalEditor::orientationEdited()
|
||||||
|
{
|
||||||
|
if (m_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_locked = true;
|
||||||
|
|
||||||
|
auto ori_ = ui->m_orientation_cb->currentData();
|
||||||
|
if (m_part->orientation() != ori_)
|
||||||
|
{
|
||||||
|
auto undo = new QPropertyUndoCommand(m_part, "orientation", m_part->property("orientation"), ori_);
|
||||||
|
undo->setText(tr("Modifier l'orientation d'une borne"));
|
||||||
|
undoStack().push(undo);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::nameEdited
|
||||||
|
*/
|
||||||
|
void TerminalEditor::nameEdited()
|
||||||
|
{
|
||||||
|
if (m_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_locked = true;
|
||||||
|
QString name_(ui->m_name_le->text());
|
||||||
|
|
||||||
|
if (m_part->name() != name_)
|
||||||
|
{
|
||||||
|
auto undo = new QPropertyUndoCommand(m_part, "name", m_part->property("name"), name_);
|
||||||
|
undo->setText(tr("Modifier le nom du terminal"));
|
||||||
|
undoStack().push(undo);
|
||||||
|
}
|
||||||
|
m_locked=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::typeEdited
|
||||||
|
*/
|
||||||
|
void TerminalEditor::typeEdited()
|
||||||
|
{
|
||||||
|
if (m_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_locked = true;
|
||||||
|
|
||||||
|
auto type = ui->m_type_cb->currentData();
|
||||||
|
if (type != m_part->terminalType()) {
|
||||||
|
auto undo = new QPropertyUndoCommand(m_part, "terminal_type", m_part->terminalType(), type);
|
||||||
|
undo->setText(tr("Modifier le type d'une borne"));
|
||||||
|
undoStack().push(undo);
|
||||||
|
}
|
||||||
|
m_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalEditor::activeConnections
|
||||||
|
* Active connection between the widgets used in this editor
|
||||||
|
* and method of this class.
|
||||||
|
* @param active
|
||||||
|
*/
|
||||||
|
void TerminalEditor::activeConnections(bool active)
|
||||||
|
{
|
||||||
|
if (active) {
|
||||||
|
m_editor_connections << connect(ui->m_x_dsb, QOverload<qreal>::of(&QDoubleSpinBox::valueChanged),
|
||||||
|
this, &TerminalEditor::posEdited);
|
||||||
|
m_editor_connections << connect(ui->m_y_dsb, QOverload<qreal>::of(&QDoubleSpinBox::valueChanged),
|
||||||
|
this, &TerminalEditor::posEdited);
|
||||||
|
m_editor_connections << connect(ui->m_orientation_cb, QOverload<int>::of(&QComboBox::activated),
|
||||||
|
this, &TerminalEditor::orientationEdited);
|
||||||
|
m_editor_connections << connect(ui->m_name_le, &QLineEdit::editingFinished,
|
||||||
|
this, &TerminalEditor::nameEdited);
|
||||||
|
m_editor_connections << connect(ui->m_type_cb, QOverload<int>::of(&QComboBox::activated),
|
||||||
|
this, &TerminalEditor::typeEdited);
|
||||||
|
} else {
|
||||||
|
for (auto const & con : qAsConst(m_editor_connections)) {
|
||||||
|
QObject::disconnect(con);
|
||||||
|
}
|
||||||
|
m_editor_connections.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerminalEditor::activeChangeConnections(bool active)
|
||||||
|
{
|
||||||
|
if (active)
|
||||||
|
{
|
||||||
|
m_change_connections << connect(m_part, &PartTerminal::xChanged, this, &TerminalEditor::updateForm);
|
||||||
|
m_change_connections << connect(m_part, &PartTerminal::yChanged, this, &TerminalEditor::updateForm);
|
||||||
|
m_change_connections << connect(m_part, &PartTerminal::orientationChanged, this, &TerminalEditor::updateForm);
|
||||||
|
m_change_connections << connect(m_part, &PartTerminal::nameChanged, this, &TerminalEditor::updateForm);
|
||||||
|
m_change_connections << connect(m_part, &PartTerminal::terminalTypeChanged, this, &TerminalEditor::updateForm);
|
||||||
|
} else {
|
||||||
|
for (auto &con : m_change_connections) {
|
||||||
|
QObject::disconnect(con);
|
||||||
|
}
|
||||||
|
m_change_connections.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 The QElectroTech Team
|
||||||
|
This file is part of QElectroTech.
|
||||||
|
|
||||||
|
QElectroTech is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
QElectroTech is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef TERMINALEDITOR_H
|
||||||
|
#define TERMINALEDITOR_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "../elementitemeditor.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class TerminalEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PartTerminal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The TerminalEditor class
|
||||||
|
* Provide a widget used to edit the properties of a PartTerminal
|
||||||
|
*/
|
||||||
|
class TerminalEditor : public ElementItemEditor
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TerminalEditor(QETElementEditor *editor, QWidget *parent = nullptr);
|
||||||
|
~TerminalEditor() override;
|
||||||
|
|
||||||
|
void updateForm() override;
|
||||||
|
bool setPart(CustomElementPart *new_part) override;
|
||||||
|
CustomElementPart *currentPart() const override;
|
||||||
|
QList<CustomElementPart *> currentParts() const override {return QList<CustomElementPart *>();}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
void posEdited();
|
||||||
|
void orientationEdited();
|
||||||
|
void nameEdited();
|
||||||
|
void typeEdited();
|
||||||
|
void activeConnections(bool active);
|
||||||
|
void activeChangeConnections(bool active);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::TerminalEditor *ui;
|
||||||
|
QVector<QMetaObject::Connection> m_editor_connections,
|
||||||
|
m_change_connections;
|
||||||
|
PartTerminal *m_part = nullptr;
|
||||||
|
bool m_locked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TERMINALEDITOR_H
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>TerminalEditor</class>
|
||||||
|
<widget class="QWidget" name="TerminalEditor">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>511</width>
|
||||||
|
<height>236</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>y :</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="m_x_dsb">
|
||||||
|
<property name="minimum">
|
||||||
|
<double>-5000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>5000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="m_y_dsb">
|
||||||
|
<property name="minimum">
|
||||||
|
<double>-5000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>5000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Orientation :</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="m_name_le"/>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QComboBox" name="m_orientation_cb"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>x :</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Nom :</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type :</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QComboBox" name="m_type_cb"/>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<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>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -53,31 +53,6 @@ ElementsCollectionCache::ElementsCollectionCache(const QString &database_path, Q
|
|||||||
cache_db_.exec("PRAGMA synchronous = OFF");
|
cache_db_.exec("PRAGMA synchronous = OFF");
|
||||||
|
|
||||||
#if TODO_LIST
|
#if TODO_LIST
|
||||||
#pragma message("@TODO This code remove old table with mtime for create table with uuid, created at version 0,5")
|
|
||||||
#endif
|
|
||||||
//TODO This code remove old table with mtime for create table with uuid, created at version 0,5
|
|
||||||
//see to remove this code at version 0,6 or 0,7 when all users will table with uuid.
|
|
||||||
#if TODO_LIST
|
|
||||||
#pragma message("@TODO remove this code for qet 0.6 or later")
|
|
||||||
#endif
|
|
||||||
QSqlQuery table_name(cache_db_);
|
|
||||||
if (table_name.exec("PRAGMA table_info(names)"))
|
|
||||||
{
|
|
||||||
if (table_name.seek(2))
|
|
||||||
{
|
|
||||||
QString str = table_name.value(1).toString();
|
|
||||||
table_name.finish();
|
|
||||||
if (str == "mtime")
|
|
||||||
{
|
|
||||||
QSqlQuery error;
|
|
||||||
error = cache_db_.exec("DROP TABLE names");
|
|
||||||
error = cache_db_.exec("DROP TABLE pixmaps");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
table_name.finish();
|
|
||||||
}
|
|
||||||
#if TODO_LIST
|
|
||||||
#pragma message("@TODO the tables could already exist, handle that case.")
|
#pragma message("@TODO the tables could already exist, handle that case.")
|
||||||
#endif
|
#endif
|
||||||
//@TODO the tables could already exist, handle that case.
|
//@TODO the tables could already exist, handle that case.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include "elementspanelwidget.h"
|
#include "elementspanelwidget.h"
|
||||||
|
|
||||||
#include "diagram.h"
|
#include "diagram.h"
|
||||||
#include "editor/qetelementeditor.h"
|
#include "editor/ui/qetelementeditor.h"
|
||||||
#include "elementscategoryeditor.h"
|
#include "elementscategoryeditor.h"
|
||||||
#include "qetapp.h"
|
#include "qetapp.h"
|
||||||
#include "qeticons.h"
|
#include "qeticons.h"
|
||||||
|
|||||||
+2
-17
@@ -18,10 +18,10 @@
|
|||||||
#include "machine_info.h"
|
#include "machine_info.h"
|
||||||
#include "qet.h"
|
#include "qet.h"
|
||||||
#include "qetapp.h"
|
#include "qetapp.h"
|
||||||
#include "singleapplication.h"
|
|
||||||
#include "utils/macosxopenevent.h"
|
#include "utils/macosxopenevent.h"
|
||||||
|
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief myMessageOutput
|
@brief myMessageOutput
|
||||||
@@ -174,7 +174,7 @@ int main(int argc, char **argv)
|
|||||||
#pragma message("@TODO remove code for QT 6 or later")
|
#pragma message("@TODO remove code for QT 6 or later")
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
SingleApplication app(argc, argv, true);
|
QApplication app(argc, argv, true);
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
//Handle the opening of QET when user double click on a .qet .elmt .tbt file
|
//Handle the opening of QET when user double click on a .qet .elmt .tbt file
|
||||||
//or drop these same files to the QET icon of the dock
|
//or drop these same files to the QET icon of the dock
|
||||||
@@ -182,23 +182,8 @@ int main(int argc, char **argv)
|
|||||||
app.installEventFilter(&open_event);
|
app.installEventFilter(&open_event);
|
||||||
app.setStyle(QStyleFactory::create("Fusion"));
|
app.setStyle(QStyleFactory::create("Fusion"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (app.isSecondary())
|
|
||||||
{
|
|
||||||
QStringList arg_list = app.arguments();
|
|
||||||
//Remove the first argument, it's the binary file
|
|
||||||
arg_list.takeFirst();
|
|
||||||
QETArguments qetarg(arg_list);
|
|
||||||
QString message = "launched-with-args: " + QET::joinWithSpaces(
|
|
||||||
QStringList(qetarg.arguments()));
|
|
||||||
app.sendMessage(message.toUtf8());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QETApp qetapp;
|
QETApp qetapp;
|
||||||
QETApp::instance()->installEventFilter(&qetapp);
|
QETApp::instance()->installEventFilter(&qetapp);
|
||||||
QObject::connect(&app, &SingleApplication::receivedMessage,
|
|
||||||
&qetapp, &QETApp::receiveMessage);
|
|
||||||
|
|
||||||
// for debugging
|
// for debugging
|
||||||
qInstallMessageHandler(myMessageOutput);
|
qInstallMessageHandler(myMessageOutput);
|
||||||
|
|||||||
@@ -20,10 +20,14 @@
|
|||||||
#include "ElementsCollection/elementcollectionitem.h"
|
#include "ElementsCollection/elementcollectionitem.h"
|
||||||
#include "ElementsCollection/elementscollectionmodel.h"
|
#include "ElementsCollection/elementscollectionmodel.h"
|
||||||
#include "NameList/ui/namelistwidget.h"
|
#include "NameList/ui/namelistwidget.h"
|
||||||
#include "editor/qetelementeditor.h"
|
#include "editor/ui/qetelementeditor.h"
|
||||||
#include "qetmessagebox.h"
|
#include "qetmessagebox.h"
|
||||||
#include "qfilenameedit.h"
|
#include "qfilenameedit.h"
|
||||||
|
|
||||||
|
#include <QTreeView>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Constructeur
|
Constructeur
|
||||||
@param parent QWidget parent de ce dialogue
|
@param parent QWidget parent de ce dialogue
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "autoNum/assignvariables.h"
|
#include "autoNum/assignvariables.h"
|
||||||
#include "diagram.h"
|
#include "diagram.h"
|
||||||
#include "diagramview.h"
|
#include "diagramview.h"
|
||||||
#include "editor/qetelementeditor.h"
|
#include "editor/ui/qetelementeditor.h"
|
||||||
#include "exportdialog.h"
|
#include "exportdialog.h"
|
||||||
#include "qetapp.h"
|
#include "qetapp.h"
|
||||||
#include "qeticons.h"
|
#include "qeticons.h"
|
||||||
|
|||||||
@@ -0,0 +1,406 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 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 "elementdata.h"
|
||||||
|
#include "../qetxml.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
void ElementData::toSettings(QSettings &settings, const QString prefix) const {
|
||||||
|
Q_UNUSED(settings)
|
||||||
|
Q_UNUSED(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElementData::fromSettings(const QSettings &settings, const QString prefix) {
|
||||||
|
Q_UNUSED(settings)
|
||||||
|
Q_UNUSED(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement ElementData::toXml(QDomDocument &xml_element) const {
|
||||||
|
Q_UNUSED(xml_element)
|
||||||
|
return QDomElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ElementData::fromXml
|
||||||
|
* load properties from xml element.
|
||||||
|
* The tag name of xml_element must be definition
|
||||||
|
* and have an attribute "type"
|
||||||
|
* @param xml_element : tagName must be 'definition'
|
||||||
|
* @return true is successfuly loaded
|
||||||
|
*/
|
||||||
|
bool ElementData::fromXml(const QDomElement &xml_element)
|
||||||
|
{
|
||||||
|
if(xml_element.tagName() != "definition" ||
|
||||||
|
xml_element.attribute("type") != "element") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_type = typeFromString(xml_element.attribute("link_type", "simple"));
|
||||||
|
kindInfoFromXml(xml_element);
|
||||||
|
m_informations.fromXml(xml_element.firstChildElement("elementInformations"),
|
||||||
|
"elementInformation");
|
||||||
|
m_names_list.fromXml(xml_element);
|
||||||
|
|
||||||
|
auto xml_draw_info = xml_element.firstChildElement("informations");
|
||||||
|
if(xml_draw_info.tagName() == "informations") {
|
||||||
|
m_drawing_information = xml_draw_info.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDomElement ElementData::kindInfoToXml(QDomDocument &document)
|
||||||
|
{
|
||||||
|
//kindInformations
|
||||||
|
auto returned_elmt = document.createElement("kindInformations");
|
||||||
|
|
||||||
|
if (m_type == ElementData::Master)
|
||||||
|
{
|
||||||
|
auto xml_type = document.createElement("kindInformation");
|
||||||
|
xml_type.setAttribute("name", "type");
|
||||||
|
auto type_txt = document.createTextNode(masterTypeToString(m_master_type));
|
||||||
|
xml_type.appendChild(type_txt);
|
||||||
|
|
||||||
|
returned_elmt.appendChild(xml_type);
|
||||||
|
}
|
||||||
|
else if (m_type == ElementData::Slave)
|
||||||
|
{
|
||||||
|
//type
|
||||||
|
auto xml_type = document.createElement("kindInformation");
|
||||||
|
xml_type.setAttribute("name", "type");
|
||||||
|
auto type_txt = document.createTextNode(slaveTypeToString(m_slave_type));
|
||||||
|
xml_type.appendChild(type_txt);
|
||||||
|
returned_elmt.appendChild(xml_type);
|
||||||
|
|
||||||
|
//state
|
||||||
|
auto xml_state = document.createElement("kindInformation");
|
||||||
|
xml_state.setAttribute("name", "state");
|
||||||
|
auto state_txt = document.createTextNode(slaveStateToString(m_slave_state));
|
||||||
|
xml_state.appendChild(state_txt);
|
||||||
|
|
||||||
|
returned_elmt.appendChild(xml_state);
|
||||||
|
|
||||||
|
//contact count
|
||||||
|
auto xml_count = document.createElement("kindInformation");
|
||||||
|
xml_count.setAttribute("name", "number");
|
||||||
|
auto count_txt = document.createTextNode(QString::number(m_contact_count));
|
||||||
|
xml_count.appendChild(count_txt);
|
||||||
|
|
||||||
|
returned_elmt.appendChild(xml_count);
|
||||||
|
}
|
||||||
|
else if (m_type == ElementData::Terminale)
|
||||||
|
{
|
||||||
|
//type
|
||||||
|
auto xml_type = document.createElement("kindInformation");
|
||||||
|
xml_type.setAttribute("name", "type");
|
||||||
|
auto type_txt = document.createTextNode(terminalTypeToString(m_terminal_type));
|
||||||
|
xml_type.appendChild(type_txt);
|
||||||
|
returned_elmt.appendChild(xml_type);
|
||||||
|
|
||||||
|
//function
|
||||||
|
auto xml_func = document.createElement("kindInformation");
|
||||||
|
xml_func.setAttribute("name", "function");
|
||||||
|
auto func_txt = document.createTextNode(terminalFunctionToString(m_terminal_function));
|
||||||
|
xml_func.appendChild(func_txt);
|
||||||
|
returned_elmt.appendChild(xml_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returned_elmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ElementData::operator==(const ElementData &data) const
|
||||||
|
{
|
||||||
|
if (data.m_type != m_type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.m_type == ElementData::Master) {
|
||||||
|
if(data.m_master_type != m_master_type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data.m_type == ElementData::Slave) {
|
||||||
|
if (data.m_slave_state != m_slave_state ||
|
||||||
|
data.m_slave_type != m_slave_type ||
|
||||||
|
data.m_contact_count != m_contact_count) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (data.m_type == ElementData::Terminale) {
|
||||||
|
if (data.m_terminal_type != m_terminal_type ||
|
||||||
|
data.m_terminal_function != m_terminal_function) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.m_informations != m_informations) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.m_names_list != m_names_list) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_drawing_information != m_drawing_information) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ElementData::operator !=(const ElementData &data) const {
|
||||||
|
return !(*this == data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ElementData::typeToString(ElementData::Type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ElementData::Simple :
|
||||||
|
return QString("simple");
|
||||||
|
case ElementData::NextReport :
|
||||||
|
return QString ("next_report");
|
||||||
|
case ElementData::PreviousReport :
|
||||||
|
return QString("previous_report");
|
||||||
|
case ElementData::Master :
|
||||||
|
return QString("master");
|
||||||
|
case ElementData::Slave :
|
||||||
|
return QString("slave");
|
||||||
|
case ElementData::Terminale :
|
||||||
|
return QString("terminal");
|
||||||
|
default:
|
||||||
|
qDebug() << "ElementData::typeToString : type don't exist"
|
||||||
|
<< "return failsafe value 'simple'";
|
||||||
|
return QString("simple");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementData::Type ElementData::typeFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "simple") {
|
||||||
|
return ElementData::Simple;
|
||||||
|
} else if (string == "next_report") {
|
||||||
|
return ElementData::NextReport;
|
||||||
|
} else if (string == "previous_report") {
|
||||||
|
return ElementData::PreviousReport;
|
||||||
|
} else if (string == "master") {
|
||||||
|
return ElementData::Master;
|
||||||
|
} else if (string == "slave") {
|
||||||
|
return ElementData::Slave;
|
||||||
|
} else if (string == "terminal") {
|
||||||
|
return ElementData::Terminale;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return simple if nothing match
|
||||||
|
qDebug() << "ElementData::typeFromString : string "
|
||||||
|
<< string
|
||||||
|
<< " don't exist, return failsafe value 'simple";
|
||||||
|
return ElementData::Simple;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ElementData::masterTypeToString(ElementData::MasterType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ElementData::Coil:
|
||||||
|
return QString ("coil");
|
||||||
|
case ElementData::Protection:
|
||||||
|
return QString ("protection");
|
||||||
|
case ElementData::Commutator:
|
||||||
|
return QString ("commutator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementData::MasterType ElementData::masterTypeFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "coil") {
|
||||||
|
return ElementData::Coil;
|
||||||
|
} else if (string == "protection") {
|
||||||
|
return ElementData::Protection;
|
||||||
|
} else if (string == "commutator") {
|
||||||
|
return ElementData::Commutator;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ElementData::masterTypeFromString : string "
|
||||||
|
<< string
|
||||||
|
<< " don't exist, return failsafe value 'coil'";
|
||||||
|
return ElementData::Coil;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ElementData::slaveTypeToString(ElementData::SlaveType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ElementData::SSimple:
|
||||||
|
return QString ("simple");
|
||||||
|
case ElementData::Power:
|
||||||
|
return QString ("power");
|
||||||
|
case ElementData::DelayOn:
|
||||||
|
return QString("delayOn");
|
||||||
|
case ElementData::DelayOff:
|
||||||
|
return QString("delayOff");
|
||||||
|
case ElementData::delayOnOff:
|
||||||
|
return QString("delayOnOff");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementData::SlaveType ElementData::slaveTypeFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "simple") {
|
||||||
|
return ElementData::SSimple;
|
||||||
|
} else if (string == "power") {
|
||||||
|
return ElementData::Power;
|
||||||
|
} else if (string == "delayOn") {
|
||||||
|
return ElementData::DelayOn;
|
||||||
|
} else if (string == "delayOff") {
|
||||||
|
return ElementData::DelayOff;
|
||||||
|
} else if (string == "delayOnOff") {
|
||||||
|
return ElementData::delayOnOff;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ElementData::slaveTypeFromSting : string "
|
||||||
|
<< string
|
||||||
|
<< " don't exist, return failsafe value 'simple'";
|
||||||
|
return ElementData::SSimple;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ElementData::slaveStateToString(ElementData::SlaveState type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case NO:
|
||||||
|
return QString("NO");
|
||||||
|
case NC:
|
||||||
|
return QString("NC");
|
||||||
|
case SW:
|
||||||
|
return QString("SW");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementData::SlaveState ElementData::slaveStateFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "NO") {
|
||||||
|
return ElementData::NO;
|
||||||
|
} else if (string == "NC") {
|
||||||
|
return ElementData::NC;
|
||||||
|
} else if (string == "SW") {
|
||||||
|
return ElementData::SW;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ElementData::slaveStateFromString : string : "
|
||||||
|
<< string
|
||||||
|
<< " don't exist, return failsafe value 'NO'";
|
||||||
|
return ElementData::NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ElementData::terminalTypeToString(ElementData::TerminalType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case ElementData::TTGeneric :
|
||||||
|
return QString("generic");
|
||||||
|
case ElementData::Fuse :
|
||||||
|
return QString("fuse");
|
||||||
|
case ElementData::Sectional:
|
||||||
|
return QString("sectional");
|
||||||
|
case ElementData::Diode:
|
||||||
|
return QString("diode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementData::TerminalType ElementData::terminalTypeFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "generic") {
|
||||||
|
return ElementData::TTGeneric;
|
||||||
|
} else if (string == "fuse") {
|
||||||
|
return ElementData::Fuse;
|
||||||
|
} else if (string == "sectional") {
|
||||||
|
return ElementData::Sectional;
|
||||||
|
} else if (string == "diode") {
|
||||||
|
return ElementData::Diode;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ElementData::terminalTypeFromString : string : "
|
||||||
|
<< string
|
||||||
|
<< " don't exist, return failsafe value 'generic'";
|
||||||
|
return ElementData::TTGeneric;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ElementData::terminalFunctionToString(ElementData::TerminalFunction function)
|
||||||
|
{
|
||||||
|
switch (function) {
|
||||||
|
case ElementData::TFGeneric:
|
||||||
|
return QString("generic");
|
||||||
|
case ElementData::Phase:
|
||||||
|
return QString ("phase");
|
||||||
|
case ElementData::Neutral:
|
||||||
|
return QString("neutral");
|
||||||
|
case ElementData::PE:
|
||||||
|
return QString("pe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementData::TerminalFunction ElementData::terminalFunctionFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "generic") {
|
||||||
|
return ElementData::TFGeneric;
|
||||||
|
} else if (string == "phase") {
|
||||||
|
return ElementData::Phase;
|
||||||
|
} else if (string == "neutral") {
|
||||||
|
return ElementData::Neutral;
|
||||||
|
} else if (string == "pe") {
|
||||||
|
return ElementData::PE;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "ElementData::terminalFunctionFromString : string : "
|
||||||
|
<< string
|
||||||
|
<< " don't exist, return failsafe value 'generic'";
|
||||||
|
return ElementData::TFGeneric;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElementData::kindInfoFromXml(const QDomElement &xml_element)
|
||||||
|
{
|
||||||
|
if (m_type == ElementData::Master ||
|
||||||
|
m_type == ElementData::Slave ||
|
||||||
|
m_type == ElementData::Terminale)
|
||||||
|
{
|
||||||
|
auto xml_kind = xml_element.firstChildElement("kindInformations");
|
||||||
|
for (const auto &dom_elmt : QETXML::findInDomElement(xml_kind, "kindInformation"))
|
||||||
|
{
|
||||||
|
if (!dom_elmt.hasAttribute("name")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto name = dom_elmt.attribute("name");
|
||||||
|
|
||||||
|
if (m_type == ElementData::Master &&
|
||||||
|
name == "type") {
|
||||||
|
m_master_type = masterTypeFromString(dom_elmt.text());
|
||||||
|
}
|
||||||
|
else if (m_type == ElementData::Slave ) {
|
||||||
|
if (name == "type") {
|
||||||
|
m_slave_type = slaveTypeFromString(dom_elmt.text());
|
||||||
|
} else if (name == "state") {
|
||||||
|
m_slave_state = slaveStateFromString(dom_elmt.text());
|
||||||
|
} else if (name == "number") {
|
||||||
|
m_contact_count = dom_elmt.text().toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_type == ElementData::Terminale) {
|
||||||
|
if (name == "type") {
|
||||||
|
m_terminal_type = terminalTypeFromString(dom_elmt.text());
|
||||||
|
} else if (name == "function") {
|
||||||
|
m_terminal_function = terminalFunctionFromString(dom_elmt.text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 The QElectroTech Team
|
||||||
|
This file is part of QElectroTech.
|
||||||
|
|
||||||
|
QElectroTech is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
QElectroTech is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef ELEMENTDATA_H
|
||||||
|
#define ELEMENTDATA_H
|
||||||
|
|
||||||
|
#include "propertiesinterface.h"
|
||||||
|
#include "../diagramcontext.h"
|
||||||
|
#include "../NameList/nameslist.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The ElementData class
|
||||||
|
* WARNING
|
||||||
|
* This class inherit from PropertiesInterface but
|
||||||
|
* only fromXml is actually reimplemented.
|
||||||
|
*/
|
||||||
|
class ElementData : public PropertiesInterface
|
||||||
|
{
|
||||||
|
Q_GADGET
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Type {
|
||||||
|
Simple = 1,
|
||||||
|
NextReport = 2,
|
||||||
|
PreviousReport = 4,
|
||||||
|
AllReport = 6,
|
||||||
|
Master = 8,
|
||||||
|
Slave = 16,
|
||||||
|
Terminale = 32};
|
||||||
|
Q_ENUM(Type)
|
||||||
|
|
||||||
|
enum MasterType {
|
||||||
|
Coil,
|
||||||
|
Protection,
|
||||||
|
Commutator
|
||||||
|
};
|
||||||
|
Q_ENUM(MasterType)
|
||||||
|
|
||||||
|
enum SlaveType {
|
||||||
|
SSimple,
|
||||||
|
Power,
|
||||||
|
DelayOn,
|
||||||
|
DelayOff,
|
||||||
|
delayOnOff
|
||||||
|
};
|
||||||
|
Q_ENUM(SlaveType)
|
||||||
|
|
||||||
|
enum SlaveState {
|
||||||
|
NO,
|
||||||
|
NC,
|
||||||
|
SW
|
||||||
|
};
|
||||||
|
Q_ENUM(SlaveState)
|
||||||
|
|
||||||
|
enum TerminalType {
|
||||||
|
TTGeneric,
|
||||||
|
Fuse,
|
||||||
|
Sectional,
|
||||||
|
Diode
|
||||||
|
};
|
||||||
|
Q_ENUM(TerminalType)
|
||||||
|
|
||||||
|
enum TerminalFunction {
|
||||||
|
TFGeneric,
|
||||||
|
Phase,
|
||||||
|
Neutral,
|
||||||
|
PE
|
||||||
|
};
|
||||||
|
Q_ENUM(TerminalFunction)
|
||||||
|
|
||||||
|
ElementData() {}
|
||||||
|
~ElementData() override {}
|
||||||
|
|
||||||
|
void toSettings(QSettings &settings, const QString prefix = QString()) const override;
|
||||||
|
void fromSettings(const QSettings &settings, const QString prefix = QString()) override;
|
||||||
|
QDomElement toXml(QDomDocument &xml_element) const override;
|
||||||
|
bool fromXml(const QDomElement &xml_element) override;
|
||||||
|
QDomElement kindInfoToXml(QDomDocument &document);
|
||||||
|
|
||||||
|
bool operator==(const ElementData &data) const;
|
||||||
|
bool operator!=(const ElementData &data) const;
|
||||||
|
|
||||||
|
static QString typeToString(ElementData::Type type);
|
||||||
|
static ElementData::Type typeFromString(const QString &string);
|
||||||
|
|
||||||
|
static QString masterTypeToString(ElementData::MasterType type);
|
||||||
|
static ElementData::MasterType masterTypeFromString(const QString &string);
|
||||||
|
|
||||||
|
static QString slaveTypeToString (ElementData::SlaveType type);
|
||||||
|
static ElementData::SlaveType slaveTypeFromString(const QString &string);
|
||||||
|
|
||||||
|
static QString slaveStateToString(ElementData::SlaveState type);
|
||||||
|
static ElementData::SlaveState slaveStateFromString(const QString &string);
|
||||||
|
|
||||||
|
static QString terminalTypeToString(ElementData::TerminalType type);
|
||||||
|
static ElementData::TerminalType terminalTypeFromString(const QString &string);
|
||||||
|
|
||||||
|
static QString terminalFunctionToString(ElementData::TerminalFunction function);
|
||||||
|
static ElementData::TerminalFunction terminalFunctionFromString(const QString &string);
|
||||||
|
|
||||||
|
// must be public, because this class is a private member
|
||||||
|
// of Element/ element editor and they must access this data
|
||||||
|
ElementData::Type m_type = ElementData::Simple;
|
||||||
|
|
||||||
|
ElementData::MasterType m_master_type = ElementData::Coil;
|
||||||
|
|
||||||
|
ElementData::SlaveType m_slave_type = ElementData::SSimple;
|
||||||
|
ElementData::SlaveState m_slave_state = ElementData::NO;
|
||||||
|
|
||||||
|
ElementData::TerminalType m_terminal_type = ElementData::TTGeneric;
|
||||||
|
ElementData::TerminalFunction m_terminal_function = ElementData::TFGeneric;
|
||||||
|
|
||||||
|
int m_contact_count = 1;
|
||||||
|
DiagramContext m_informations;
|
||||||
|
NamesList m_names_list;
|
||||||
|
QString m_drawing_information;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void kindInfoFromXml(const QDomElement &xml_element);
|
||||||
|
};
|
||||||
|
#endif // ELEMENTDATA_H
|
||||||
@@ -1,6 +1,24 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 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 "terminaldata.h"
|
#include "terminaldata.h"
|
||||||
|
|
||||||
#include <QGraphicsObject>
|
#include <QGraphicsObject>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
TerminalData::TerminalData():
|
TerminalData::TerminalData():
|
||||||
PropertiesInterface()
|
PropertiesInterface()
|
||||||
@@ -44,8 +62,8 @@ void TerminalData::setParent(QGraphicsObject* parent)
|
|||||||
void TerminalData::toSettings(QSettings &settings, const QString prefix) const
|
void TerminalData::toSettings(QSettings &settings, const QString prefix) const
|
||||||
|
|
||||||
{
|
{
|
||||||
Q_UNUSED(settings);
|
Q_UNUSED(settings)
|
||||||
Q_UNUSED(prefix);
|
Q_UNUSED(prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,8 +76,8 @@ void TerminalData::toSettings(QSettings &settings, const QString prefix) const
|
|||||||
*/
|
*/
|
||||||
void TerminalData::fromSettings(const QSettings &settings, const QString prefix)
|
void TerminalData::fromSettings(const QSettings &settings, const QString prefix)
|
||||||
{
|
{
|
||||||
Q_UNUSED(settings);
|
Q_UNUSED(settings)
|
||||||
Q_UNUSED(prefix);
|
Q_UNUSED(prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,20 +96,17 @@ QDomElement TerminalData::toXml(QDomDocument &xml_document) const
|
|||||||
{
|
{
|
||||||
QDomElement xml_element = xml_document.createElement("terminal");
|
QDomElement xml_element = xml_document.createElement("terminal");
|
||||||
|
|
||||||
// write the position of the terminal
|
|
||||||
// ecrit la position de la borne
|
|
||||||
xml_element.setAttribute("x", QString("%1").arg(q->scenePos().x()));
|
xml_element.setAttribute("x", QString("%1").arg(q->scenePos().x()));
|
||||||
xml_element.setAttribute("y", QString("%1").arg(q->scenePos().y()));
|
xml_element.setAttribute("y", QString("%1").arg(q->scenePos().y()));
|
||||||
|
|
||||||
// Write name and number to XML
|
|
||||||
xml_element.setAttribute("uuid", m_uuid.toString());
|
xml_element.setAttribute("uuid", m_uuid.toString());
|
||||||
xml_element.setAttribute("name", m_name);
|
xml_element.setAttribute("name", m_name);
|
||||||
|
|
||||||
// write the orientation of the terminal
|
|
||||||
// ecrit l'orientation de la borne
|
|
||||||
xml_element.setAttribute("orientation",
|
xml_element.setAttribute("orientation",
|
||||||
Qet::orientationToString(m_orientation));
|
Qet::orientationToString(m_orientation));
|
||||||
|
|
||||||
|
xml_element.setAttribute("type", typeToString(m_type));
|
||||||
|
|
||||||
return(xml_element);
|
return(xml_element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,5 +152,45 @@ bool TerminalData::fromXml (const QDomElement &xml_element)
|
|||||||
m_orientation = Qet::orientationFromString(
|
m_orientation = Qet::orientationFromString(
|
||||||
xml_element.attribute("orientation"));
|
xml_element.attribute("orientation"));
|
||||||
|
|
||||||
|
m_type = typeFromString(xml_element.attribute("type"));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalData::typeToString
|
||||||
|
* @param type
|
||||||
|
* @return type into a QString
|
||||||
|
*/
|
||||||
|
QString TerminalData::typeToString(TerminalData::Type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case Generic:
|
||||||
|
return QString("Generic");
|
||||||
|
case Inner :
|
||||||
|
return QString("Inner");
|
||||||
|
case Outer :
|
||||||
|
return QString("Outer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TerminalData::typeFromString
|
||||||
|
* @param string
|
||||||
|
* @return The type describe in string to TerminalData::Type.
|
||||||
|
* if string doesn't describe a type, TerminalData::Generic is returned
|
||||||
|
*/
|
||||||
|
TerminalData::Type TerminalData::typeFromString(const QString &string)
|
||||||
|
{
|
||||||
|
if (string == "Generic") {
|
||||||
|
return TerminalData::Generic;
|
||||||
|
} else if (string == "Inner") {
|
||||||
|
return TerminalData::Inner;
|
||||||
|
} else if (string == "Outer") {
|
||||||
|
return TerminalData::Outer;
|
||||||
|
} else {
|
||||||
|
qDebug() << "TerminalData::typeFromString, argument string is invalid"
|
||||||
|
" failsafe type 'TerminalData::Generic' is returned";
|
||||||
|
return TerminalData::Generic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2006-2021 The QElectroTech Team
|
||||||
|
This file is part of QElectroTech.
|
||||||
|
|
||||||
|
QElectroTech is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
QElectroTech is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
#ifndef TERMINALDATA_H
|
#ifndef TERMINALDATA_H
|
||||||
#define TERMINALDATA_H
|
#define TERMINALDATA_H
|
||||||
|
|
||||||
@@ -18,10 +35,19 @@ class QGraphicsObject;
|
|||||||
*/
|
*/
|
||||||
class TerminalData : public PropertiesInterface
|
class TerminalData : public PropertiesInterface
|
||||||
{
|
{
|
||||||
|
Q_GADGET
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum Type {
|
||||||
|
Generic,
|
||||||
|
Inner,
|
||||||
|
Outer
|
||||||
|
};
|
||||||
|
Q_ENUM(Type)
|
||||||
|
|
||||||
TerminalData();
|
TerminalData();
|
||||||
TerminalData(QGraphicsObject* parent);
|
TerminalData(QGraphicsObject* parent);
|
||||||
~TerminalData();
|
~TerminalData() override;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
@@ -33,6 +59,9 @@ class TerminalData : public PropertiesInterface
|
|||||||
QDomElement toXml(QDomDocument &xml_element) const override;
|
QDomElement toXml(QDomDocument &xml_element) const override;
|
||||||
bool fromXml(const QDomElement &xml_element) override;
|
bool fromXml(const QDomElement &xml_element) override;
|
||||||
|
|
||||||
|
static QString typeToString(TerminalData::Type type);
|
||||||
|
static TerminalData::Type typeFromString(const QString &string);
|
||||||
|
|
||||||
// must be public, because this class is a private member
|
// must be public, because this class is a private member
|
||||||
// of PartTerminal/Terminal and they must access this data
|
// of PartTerminal/Terminal and they must access this data
|
||||||
public:
|
public:
|
||||||
@@ -46,7 +75,7 @@ class TerminalData : public PropertiesInterface
|
|||||||
Position of the second point of the terminal
|
Position of the second point of the terminal
|
||||||
in scene coordinates
|
in scene coordinates
|
||||||
*/
|
*/
|
||||||
QPointF second_point;
|
QPointF m_second_point;
|
||||||
/**
|
/**
|
||||||
@brief m_uuid
|
@brief m_uuid
|
||||||
Uuid of the terminal.
|
Uuid of the terminal.
|
||||||
@@ -80,6 +109,9 @@ class TerminalData : public PropertiesInterface
|
|||||||
PartTerminal and Terminal have access to it.
|
PartTerminal and Terminal have access to it.
|
||||||
*/
|
*/
|
||||||
QPointF m_pos;
|
QPointF m_pos;
|
||||||
|
|
||||||
|
TerminalData::Type m_type = TerminalData::Generic;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QGraphicsObject* q{nullptr};
|
QGraphicsObject* q{nullptr};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,74 +1,77 @@
|
|||||||
/**
|
/**
|
||||||
* pugixml parser - version 1.10
|
* pugixml parser - version 1.11
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
* Copyright (C) 2006-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
* Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||||
* Report bugs and download new versions at https://pugixml.org/
|
* Report bugs and download new versions at https://pugixml.org/
|
||||||
*
|
*
|
||||||
* This library is distributed under the MIT License. See notice at the end
|
* This library is distributed under the MIT License. See notice at the end
|
||||||
* of this file.
|
* of this file.
|
||||||
*
|
*
|
||||||
* This work is based on the pugxml parser, which is:
|
* This work is based on the pugxml parser, which is:
|
||||||
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
|
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HEADER_PUGICONFIG_HPP
|
#ifndef HEADER_PUGICONFIG_HPP
|
||||||
#define HEADER_PUGICONFIG_HPP
|
#define HEADER_PUGICONFIG_HPP
|
||||||
|
|
||||||
// Uncomment this to enable wchar_t mode
|
// Uncomment this to enable wchar_t mode
|
||||||
// #define PUGIXML_WCHAR_MODE
|
// #define PUGIXML_WCHAR_MODE
|
||||||
|
|
||||||
// Uncomment this to enable compact mode
|
// Uncomment this to enable compact mode
|
||||||
// #define PUGIXML_COMPACT
|
// #define PUGIXML_COMPACT
|
||||||
|
|
||||||
// Uncomment this to disable XPath
|
// Uncomment this to disable XPath
|
||||||
// #define PUGIXML_NO_XPATH
|
// #define PUGIXML_NO_XPATH
|
||||||
|
|
||||||
// Uncomment this to disable STL
|
// Uncomment this to disable STL
|
||||||
// #define PUGIXML_NO_STL
|
// #define PUGIXML_NO_STL
|
||||||
|
|
||||||
// Uncomment this to disable exceptions
|
// Uncomment this to disable exceptions
|
||||||
// #define PUGIXML_NO_EXCEPTIONS
|
// #define PUGIXML_NO_EXCEPTIONS
|
||||||
|
|
||||||
// Set this to control attributes for public classes/functions, i.e.:
|
// Set this to control attributes for public classes/functions, i.e.:
|
||||||
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
|
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
|
||||||
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
|
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
|
||||||
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
|
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
|
||||||
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
|
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
|
||||||
|
|
||||||
// Tune these constants to adjust memory-related behavior
|
// Tune these constants to adjust memory-related behavior
|
||||||
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
|
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
|
||||||
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
|
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
|
||||||
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
|
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
|
||||||
|
|
||||||
// Uncomment this to switch to header-only version
|
// Tune this constant to adjust max nesting for XPath queries
|
||||||
// #define PUGIXML_HEADER_ONLY
|
// #define PUGIXML_XPATH_DEPTH_LIMIT 1024
|
||||||
|
|
||||||
// Uncomment this to enable long long support
|
// Uncomment this to switch to header-only version
|
||||||
// #define PUGIXML_HAS_LONG_LONG
|
// #define PUGIXML_HEADER_ONLY
|
||||||
|
|
||||||
#endif
|
// Uncomment this to enable long long support
|
||||||
|
// #define PUGIXML_HAS_LONG_LONG
|
||||||
/**
|
|
||||||
* Copyright (c) 2006-2019 Arseny Kapoulkine
|
#endif
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person
|
/**
|
||||||
* obtaining a copy of this software and associated documentation
|
* Copyright (c) 2006-2020 Arseny Kapoulkine
|
||||||
* files (the "Software"), to deal in the Software without
|
*
|
||||||
* restriction, including without limitation the rights to use,
|
* Permission is hereby granted, free of charge, to any person
|
||||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* obtaining a copy of this software and associated documentation
|
||||||
* copies of the Software, and to permit persons to whom the
|
* files (the "Software"), to deal in the Software without
|
||||||
* Software is furnished to do so, subject to the following
|
* restriction, including without limitation the rights to use,
|
||||||
* conditions:
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
*
|
* copies of the Software, and to permit persons to whom the
|
||||||
* The above copyright notice and this permission notice shall be
|
* Software is furnished to do so, subject to the following
|
||||||
* included in all copies or substantial portions of the Software.
|
* conditions:
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* The above copyright notice and this permission notice shall be
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
* included in all copies or substantial portions of the Software.
|
||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
*
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
*/
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|||||||
+13020
-12948
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user