mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-06-10 12:53:14 +02:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f1567ec97 | |||
| e152717a05 | |||
| 0f645e9b76 | |||
| 821e681520 | |||
| d27bc35022 | |||
| 61d3adad9b |
@@ -0,0 +1,20 @@
|
|||||||
|
name: Publish Candidate Snap
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "snap/latest/candidate"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish_amd64:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: snapcore/action-build@v1
|
||||||
|
id: build
|
||||||
|
- uses: snapcore/action-publish@v1
|
||||||
|
with:
|
||||||
|
store_login: ${{ secrets.STORE_LOGIN }}
|
||||||
|
snap: ${{ steps.build.outputs.snap }}
|
||||||
|
release: candidate
|
||||||
+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.9.0
|
VERSION 0.8.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,79 +1,12 @@
|
|||||||
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,40 +1,43 @@
|
|||||||
cmake_minimum_required(VERSION 3.7.0)
|
cmake_minimum_required(VERSION 3.1.0)
|
||||||
|
|
||||||
project(SingleApplication LANGUAGES CXX)
|
project(SingleApplication)
|
||||||
|
|
||||||
|
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
|
||||||
set(QT_COMPONENTS Core Network)
|
find_package(Qt5Network)
|
||||||
set(QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Network)
|
|
||||||
|
|
||||||
if(QAPPLICATION_CLASS STREQUAL QApplication)
|
if(QAPPLICATION_CLASS STREQUAL QApplication)
|
||||||
list(APPEND QT_COMPONENTS Widgets)
|
find_package(Qt5 COMPONENTS Widgets REQUIRED)
|
||||||
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Widgets)
|
|
||||||
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
|
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
|
||||||
list(APPEND QT_COMPONENTS Gui)
|
find_package(Qt5 COMPONENTS Gui REQUIRED)
|
||||||
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Gui)
|
|
||||||
else()
|
else()
|
||||||
set(QAPPLICATION_CLASS QCoreApplication)
|
find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
|
||||||
|
|
||||||
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED)
|
# Link dependencies
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Network)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${QT_LIBRARIES})
|
if(QAPPLICATION_CLASS STREQUAL QApplication)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)
|
||||||
|
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui)
|
||||||
|
else()
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core)
|
||||||
|
endif()
|
||||||
|
|
||||||
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 - 2020
|
Copyright (c) Itay Grudev 2015 - 2016
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+18
-45
@@ -1,8 +1,7 @@
|
|||||||
SingleApplication
|
SingleApplication
|
||||||
=================
|
=================
|
||||||
[](https://github.com/itay-grudev/SingleApplication/actions)
|
|
||||||
|
|
||||||
This is a replacement of the QtSingleApplication for `Qt5` and `Qt6`.
|
This is a replacement of the QtSingleApplication for `Qt5`.
|
||||||
|
|
||||||
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)
|
||||||
@@ -16,6 +15,18 @@ 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:
|
||||||
|
|
||||||
@@ -32,7 +43,8 @@ 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. Here is how:
|
submodule to your project and include it's contents with a `.pri` file. Here is
|
||||||
|
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
|
||||||
@@ -54,27 +66,13 @@ 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
|
||||||
@@ -139,22 +137,13 @@ 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, QString userData = QString() )
|
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 )
|
||||||
```
|
```
|
||||||
|
|
||||||
Depending on whether `allowSecondary` is set, this constructor may terminate
|
Depending on whether `allowSecondary` is set, this constructor may terminate
|
||||||
@@ -163,7 +152,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. Setting `userData` provides additional data that will isolate this instance from other instances that do not have the same (or any) user data set.
|
milliseconds to wait for blocking operations.
|
||||||
|
|
||||||
*__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.*
|
||||||
@@ -215,22 +204,6 @@ 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
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
#include "singleapplication.h"
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
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)
|
|
||||||
|
|
||||||
Executable → Regular
Executable → Regular
-2
@@ -5,7 +5,5 @@ 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
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(".", SLOT(pointClicked()));
|
Button *pointButton = createButton(tr("."), SLOT(pointClicked()));
|
||||||
Button *changeSignButton = createButton("\302\261", SLOT(changeSignClicked()));
|
Button *changeSignButton = createButton(tr("\302\261"), SLOT(changeSignClicked()));
|
||||||
|
|
||||||
Button *backspaceButton = createButton("Backspace", SLOT(backspaceClicked()));
|
Button *backspaceButton = createButton(tr("Backspace"), SLOT(backspaceClicked()));
|
||||||
Button *clearButton = createButton("Clear", SLOT(clear()));
|
Button *clearButton = createButton(tr("Clear"), SLOT(clear()));
|
||||||
Button *clearAllButton = createButton("Clear All", SLOT(clearAll()));
|
Button *clearAllButton = createButton(tr("Clear All"), SLOT(clearAll()));
|
||||||
|
|
||||||
Button *clearMemoryButton = createButton("MC", SLOT(clearMemory()));
|
Button *clearMemoryButton = createButton(tr("MC"), SLOT(clearMemory()));
|
||||||
Button *readMemoryButton = createButton("MR", SLOT(readMemory()));
|
Button *readMemoryButton = createButton(tr("MR"), SLOT(readMemory()));
|
||||||
Button *setMemoryButton = createButton("MS", SLOT(setMemory()));
|
Button *setMemoryButton = createButton(tr("MS"), SLOT(setMemory()));
|
||||||
Button *addToMemoryButton = createButton("M+", SLOT(addToMemory()));
|
Button *addToMemoryButton = createButton(tr("M+"), SLOT(addToMemory()));
|
||||||
|
|
||||||
Button *divisionButton = createButton("\303\267", SLOT(multiplicativeOperatorClicked()));
|
Button *divisionButton = createButton(tr("\303\267"), SLOT(multiplicativeOperatorClicked()));
|
||||||
Button *timesButton = createButton("\303\227", SLOT(multiplicativeOperatorClicked()));
|
Button *timesButton = createButton(tr("\303\227"), SLOT(multiplicativeOperatorClicked()));
|
||||||
Button *minusButton = createButton("-", SLOT(additiveOperatorClicked()));
|
Button *minusButton = createButton(tr("-"), SLOT(additiveOperatorClicked()));
|
||||||
Button *plusButton = createButton("+", SLOT(additiveOperatorClicked()));
|
Button *plusButton = createButton(tr("+"), SLOT(additiveOperatorClicked()));
|
||||||
|
|
||||||
Button *squareRootButton = createButton("Sqrt", SLOT(unaryOperatorClicked()));
|
Button *squareRootButton = createButton(tr("Sqrt"), SLOT(unaryOperatorClicked()));
|
||||||
Button *powerButton = createButton("x\302\262", SLOT(unaryOperatorClicked()));
|
Button *powerButton = createButton(tr("x\302\262"), SLOT(unaryOperatorClicked()));
|
||||||
Button *reciprocalButton = createButton("1/x", SLOT(unaryOperatorClicked()));
|
Button *reciprocalButton = createButton(tr("1/x"), SLOT(unaryOperatorClicked()));
|
||||||
Button *equalButton = createButton("=", SLOT(equalClicked()));
|
Button *equalButton = createButton(tr("="), 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("Calculator");
|
setWindowTitle(tr("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 == "Sqrt") {
|
if (clickedOperator == tr("Sqrt")) {
|
||||||
if (operand < 0.0) {
|
if (operand < 0.0) {
|
||||||
abortOperation();
|
abortOperation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = std::sqrt(operand);
|
result = std::sqrt(operand);
|
||||||
} else if (clickedOperator == "x\302\262") {
|
} else if (clickedOperator == tr("x\302\262")) {
|
||||||
result = std::pow(operand, 2.0);
|
result = std::pow(operand, 2.0);
|
||||||
} else if (clickedOperator == "1/x") {
|
} else if (clickedOperator == tr("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() + ".");
|
display->setText(display->text() + tr("."));
|
||||||
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("-");
|
text.prepend(tr("-"));
|
||||||
} 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("####");
|
display->setText(tr("####"));
|
||||||
}
|
}
|
||||||
//! [36]
|
//! [36]
|
||||||
|
|
||||||
//! [38]
|
//! [38]
|
||||||
bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
|
bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
|
||||||
{
|
{
|
||||||
if (pendingOperator == "+") {
|
if (pendingOperator == tr("+")) {
|
||||||
sumSoFar += rightOperand;
|
sumSoFar += rightOperand;
|
||||||
} else if (pendingOperator == "-") {
|
} else if (pendingOperator == tr("-")) {
|
||||||
sumSoFar -= rightOperand;
|
sumSoFar -= rightOperand;
|
||||||
} else if (pendingOperator == "\303\227") {
|
} else if (pendingOperator == tr("\303\227")) {
|
||||||
factorSoFar *= rightOperand;
|
factorSoFar *= rightOperand;
|
||||||
} else if (pendingOperator == "\303\267") {
|
} else if (pendingOperator == tr("\303\267")) {
|
||||||
if (rightOperand == 0.0)
|
if (rightOperand == 0.0)
|
||||||
return false;
|
return false;
|
||||||
factorSoFar /= rightOperand;
|
factorSoFar /= rightOperand;
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
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)
|
|
||||||
Executable → Regular
-3
@@ -11,9 +11,6 @@ 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(
|
||||||
|
|||||||
Executable → Regular
@@ -1,6 +1,6 @@
|
|||||||
// The MIT License (MIT)
|
// The MIT License (MIT)
|
||||||
//
|
//
|
||||||
// Copyright (c) Itay Grudev 2015 - 2020
|
// Copyright (c) Itay Grudev 2015 - 2018
|
||||||
//
|
//
|
||||||
// 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,255 +20,176 @@
|
|||||||
// 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/QElapsedTimer>
|
#include <QtCore/QTime>
|
||||||
|
#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 allowSecondary Whether to enable secondary instance support
|
@param {bool} allowSecondaryInstances
|
||||||
* @param options Optional flags to toggle specific behaviour
|
*/
|
||||||
* @param timeout Maximum time blocking functions are allowed during app load
|
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout )
|
||||||
*/
|
: 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;
|
||||||
|
|
||||||
// Add any unique user data
|
// Generating an application ID used for identifying the shared memory
|
||||||
if ( ! userData.isEmpty() )
|
// block and QLocalServer
|
||||||
d->addAppData( userData );
|
d->genBlockServerName();
|
||||||
|
|
||||||
// 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
|
||||||
if( ! d->memory->lock() ){
|
d->memory->lock();
|
||||||
qCritical() << "SingleApplication: Unable to lock memory block after create.";
|
d->initializeMemoryBlock();
|
||||||
abortSafely();
|
d->memory->unlock();
|
||||||
}
|
} else {
|
||||||
d->initializeMemoryBlock();
|
// Attempt to attach to the memory segment
|
||||||
} else {
|
if( ! d->memory->attach() ) {
|
||||||
if( d->memory->error() == QSharedMemory::AlreadyExists ){
|
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
|
||||||
// Attempt to attach to the memory segment
|
qCritical() << d->memory->errorString();
|
||||||
if( ! d->memory->attach() ){
|
delete d;
|
||||||
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
|
::exit( EXIT_FAILURE );
|
||||||
abortSafely();
|
}
|
||||||
}
|
}
|
||||||
if( ! d->memory->lock() ){
|
|
||||||
qCritical() << "SingleApplication: Unable to lock memory block after attach.";
|
|
||||||
abortSafely();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qCritical() << "SingleApplication: Unable to create block.";
|
|
||||||
abortSafely();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *inst = static_cast<InstancesInfo*>( d->memory->data() );
|
InstancesInfo* 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 ) {
|
||||||
// If the shared memory block's checksum is valid continue
|
d->memory->lock();
|
||||||
if( d->blockChecksum() == inst->checksum ) break;
|
|
||||||
|
|
||||||
// If more than 5s have elapsed, assume the primary instance crashed and
|
if( d->blockChecksum() == inst->checksum ) break;
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise wait for a random period and try again. The random sleep here
|
if( time.elapsed() > 5000 ) {
|
||||||
// limits the probability of a collision between two racing apps and
|
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
||||||
// allows the app to initialise faster
|
d->initializeMemoryBlock();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( inst->primary == false ){
|
d->memory->unlock();
|
||||||
d->startPrimary();
|
|
||||||
if( ! d->memory->unlock() ){
|
|
||||||
qDebug() << "SingleApplication: Unable to unlock memory after primary start.";
|
|
||||||
qDebug() << d->memory->errorString();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if another instance can be started
|
// Random sleep here limits the probability of a collision between two racing apps
|
||||||
if( allowSecondary ){
|
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) // ### Qt 6: remove
|
||||||
d->startSecondary();
|
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() );
|
||||||
if( d->options & Mode::SecondaryNotification ){
|
QThread::sleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 ) );
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
|
#else
|
||||||
}
|
#if TODO_LIST
|
||||||
if( ! d->memory->unlock() ){
|
#pragma message("@TODO remove code for QT 5.10 or later")
|
||||||
qDebug() << "SingleApplication: Unable to unlock memory after secondary start.";
|
#endif
|
||||||
qDebug() << d->memory->errorString();
|
quint32 value = QRandomGenerator::global()->generate();
|
||||||
}
|
QThread::sleep(8 + static_cast<unsigned long>(value / RAND_MAX * 10));
|
||||||
return;
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ! d->memory->unlock() ){
|
if( inst->primary == false) {
|
||||||
qDebug() << "SingleApplication: Unable to unlock memory at end of execution.";
|
d->startPrimary();
|
||||||
qDebug() << d->memory->errorString();
|
d->memory->unlock();
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
|
// Check if another instance can be started
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
delete d;
|
d->memory->unlock();
|
||||||
|
|
||||||
::exit( EXIT_SUCCESS );
|
d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
|
||||||
|
|
||||||
|
delete d;
|
||||||
|
|
||||||
|
::exit( EXIT_SUCCESS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Destructor
|
||||||
|
*/
|
||||||
SingleApplication::~SingleApplication()
|
SingleApplication::~SingleApplication()
|
||||||
{
|
{
|
||||||
Q_D( SingleApplication );
|
Q_D(SingleApplication);
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool SingleApplication::isPrimary()
|
||||||
* Checks if the current application instance is primary.
|
|
||||||
* @return Returns true if the instance is primary, false otherwise.
|
|
||||||
*/
|
|
||||||
bool SingleApplication::isPrimary() const
|
|
||||||
{
|
{
|
||||||
Q_D( const SingleApplication );
|
Q_D(SingleApplication);
|
||||||
return d->server != nullptr;
|
return d->server != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool SingleApplication::isSecondary()
|
||||||
* Checks if the current application instance is secondary.
|
|
||||||
* @return Returns true if the instance is secondary, false otherwise.
|
|
||||||
*/
|
|
||||||
bool SingleApplication::isSecondary() const
|
|
||||||
{
|
{
|
||||||
Q_D( const SingleApplication );
|
Q_D(SingleApplication);
|
||||||
return d->server == nullptr;
|
return d->server == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
quint32 SingleApplication::instanceId()
|
||||||
* 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( const SingleApplication );
|
Q_D(SingleApplication);
|
||||||
return d->instanceNumber;
|
return d->instanceNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
qint64 SingleApplication::primaryPid()
|
||||||
* 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( const SingleApplication );
|
Q_D(SingleApplication);
|
||||||
return d->primaryPid();
|
return d->primaryPid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool SingleApplication::sendMessage( QByteArray message, int timeout )
|
||||||
* 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( const SingleApplication );
|
Q_D(SingleApplication);
|
||||||
return d->primaryUser();
|
|
||||||
}
|
// Nobody to connect to
|
||||||
|
if( isPrimary() ) return false;
|
||||||
/**
|
|
||||||
* Returns the username the current instance is running as.
|
// Make sure the socket is connected
|
||||||
* @return Returns the username the current instance is running as.
|
d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect );
|
||||||
*/
|
|
||||||
QString SingleApplication::currentUser() const
|
d->socket->write( message );
|
||||||
{
|
bool dataWritten = d->socket->waitForBytesWritten( timeout );
|
||||||
return SingleApplicationPrivate::getUsername();
|
d->socket->flush();
|
||||||
}
|
return dataWritten;
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends message to the Primary Instance.
|
|
||||||
* @param message The message to send.
|
|
||||||
* @param timeout the maximum timeout in milliseconds for blocking functions.
|
|
||||||
* @return true if the message was sent successfuly, false otherwise.
|
|
||||||
*/
|
|
||||||
bool SingleApplication::sendMessage( const QByteArray &message, int timeout )
|
|
||||||
{
|
|
||||||
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,6 +25,7 @@
|
|||||||
|
|
||||||
#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
|
||||||
@@ -35,118 +36,99 @@
|
|||||||
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
|
||||||
|
|
||||||
using app_t = QAPPLICATION_CLASS;
|
typedef QAPPLICATION_CLASS app_t;
|
||||||
|
|
||||||
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, const QString &userData = {} );
|
explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
|
||||||
~SingleApplication() override;
|
~SingleApplication();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns if the instance is the primary instance
|
@brief Returns if the instance is the primary instance
|
||||||
* @returns {bool}
|
@returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isPrimary() const;
|
bool isPrimary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns if the instance is a secondary instance
|
@brief Returns if the instance is a secondary instance
|
||||||
* @returns {bool}
|
@returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isSecondary() const;
|
bool isSecondary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a unique identifier for the current instance
|
@brief Returns a unique identifier for the current instance
|
||||||
* @returns {qint32}
|
@returns {qint32}
|
||||||
*/
|
*/
|
||||||
quint32 instanceId() const;
|
quint32 instanceId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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() const;
|
qint64 primaryPid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the username of the user running the primary instance
|
@brief Sends a message to the primary instance. Returns true on success.
|
||||||
* @returns {QString}
|
@param {int} timeout - Timeout for connecting
|
||||||
*/
|
@returns {bool}
|
||||||
QString primaryUser() const;
|
@note sendMessage() will return false if invoked from the primary
|
||||||
|
instance.
|
||||||
/**
|
*/
|
||||||
* @brief Returns the username of the current user
|
bool sendMessage( QByteArray message, int timeout = 100 );
|
||||||
* @returns {QString}
|
|
||||||
*/
|
Q_SIGNALS:
|
||||||
QString currentUser() const;
|
void instanceStarted();
|
||||||
|
void receivedMessage( quint32 instanceId, QByteArray message );
|
||||||
/**
|
|
||||||
* @brief Sends a message to the primary instance. Returns true on success.
|
private:
|
||||||
* @param {int} timeout - Timeout for connecting
|
SingleApplicationPrivate *d_ptr;
|
||||||
* @returns {bool}
|
Q_DECLARE_PRIVATE(SingleApplication)
|
||||||
* @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,8 +1,7 @@
|
|||||||
QT += core network
|
QT += core network
|
||||||
CONFIG += c++11
|
CONFIG += c++17
|
||||||
|
|
||||||
HEADERS += $$PWD/SingleApplication \
|
HEADERS += $$PWD/singleapplication.h \
|
||||||
$$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 - 2020
|
// Copyright (c) Itay Grudev 2015 - 2018
|
||||||
//
|
//
|
||||||
// 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,454 +33,412 @@
|
|||||||
#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
|
||||||
#ifndef NOMINMAX
|
#include <windows.h>
|
||||||
#define NOMINMAX 1
|
#include <lmcons.h>
|
||||||
#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 = 0;
|
instanceNumber = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleApplicationPrivate::~SingleApplicationPrivate()
|
SingleApplicationPrivate::~SingleApplicationPrivate()
|
||||||
{
|
{
|
||||||
if( socket != nullptr ){
|
if( socket != nullptr ) {
|
||||||
socket->close();
|
socket->close();
|
||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( memory != nullptr ){
|
memory->lock();
|
||||||
memory->lock();
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
auto *inst = static_cast<InstancesInfo*>(memory->data());
|
if( server != nullptr ) {
|
||||||
if( server != nullptr ){
|
server->close();
|
||||||
server->close();
|
delete server;
|
||||||
delete server;
|
inst->primary = false;
|
||||||
inst->primary = false;
|
inst->primaryPid = -1;
|
||||||
inst->primaryPid = -1;
|
inst->checksum = blockChecksum();
|
||||||
inst->primaryUser[0] = '\0';
|
}
|
||||||
inst->checksum = blockChecksum();
|
memory->unlock();
|
||||||
}
|
|
||||||
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 ( ! appDataList.isEmpty() )
|
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ) {
|
||||||
appData.addData( appDataList.join( "" ).toUtf8() );
|
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
|
||||||
|
}
|
||||||
|
|
||||||
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){
|
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ) {
|
||||||
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 ) {
|
||||||
appData.addData( getUsername().toUtf8() );
|
#ifdef Q_OS_WIN
|
||||||
}
|
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() const
|
void SingleApplicationPrivate::initializeMemoryBlock()
|
||||||
{
|
{
|
||||||
auto *inst = static_cast<InstancesInfo*>( memory->data() );
|
InstancesInfo* 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->primaryUser[0] = '\0';
|
inst->checksum = blockChecksum();
|
||||||
inst->checksum = blockChecksum();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::startPrimary()
|
void SingleApplicationPrivate::startPrimary()
|
||||||
{
|
{
|
||||||
// Reset the number of connections
|
Q_Q(SingleApplication);
|
||||||
auto *inst = static_cast <InstancesInfo*>( memory->data() );
|
|
||||||
|
|
||||||
inst->primary = true;
|
// Successful creation means that no main process exists
|
||||||
inst->primaryPid = QCoreApplication::applicationPid();
|
// So we start a QLocalServer to listen for connections
|
||||||
qstrncpy( inst->primaryUser, getUsername().toUtf8().data(), sizeof(inst->primaryUser) );
|
QLocalServer::removeServer( blockServerName );
|
||||||
inst->checksum = blockChecksum();
|
server = new QLocalServer();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
|
void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
|
||||||
{
|
{
|
||||||
QElapsedTimer time;
|
// Connect to the Local Server of the Primary Instance if not already
|
||||||
time.start();
|
// connected.
|
||||||
|
if( socket == nullptr ) {
|
||||||
|
socket = new QLocalSocket();
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to the Local Server of the Primary Instance if not already
|
// If already connected - we are done;
|
||||||
// connected.
|
if( socket->state() == QLocalSocket::ConnectedState )
|
||||||
if( socket == nullptr ){
|
return;
|
||||||
socket = new QLocalSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( socket->state() == QLocalSocket::ConnectedState ) return true;
|
// If not connect
|
||||||
|
if( socket->state() == QLocalSocket::UnconnectedState ||
|
||||||
|
socket->state() == QLocalSocket::ClosingState ) {
|
||||||
|
socket->connectToServer( blockServerName );
|
||||||
|
}
|
||||||
|
|
||||||
if( socket->state() != QLocalSocket::ConnectedState ){
|
// Wait for being connected
|
||||||
|
if( socket->state() == QLocalSocket::ConnectingState ) {
|
||||||
|
socket->waitForConnected( msecs );
|
||||||
|
}
|
||||||
|
|
||||||
while( true ){
|
// Initialisation message according to the SingleApplication protocol
|
||||||
randomSleep();
|
if( socket->state() == QLocalSocket::ConnectedState ) {
|
||||||
|
// Notify the parent that a new instance had been started;
|
||||||
if( socket->state() != QLocalSocket::ConnectingState )
|
QByteArray initMsg;
|
||||||
socket->connectToServer( blockServerName );
|
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
||||||
|
|
||||||
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)
|
|
||||||
quint16 checksum = qChecksum(QByteArray(initMsg, static_cast<quint32>(initMsg.length())));
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
||||||
|
quint16 checksum =
|
||||||
|
qChecksum(
|
||||||
|
initMsg.constData(),
|
||||||
|
static_cast<quint32>(initMsg.length()));
|
||||||
#else
|
#else
|
||||||
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
#if TODO_LIST
|
||||||
|
#pragma message("@TODO remove code for QT 6 or later")
|
||||||
#endif
|
#endif
|
||||||
writeStream << checksum;
|
quint16 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 );
|
||||||
bool result = socket->waitForBytesWritten( static_cast<int>(msecs - time.elapsed()) );
|
socket->flush();
|
||||||
socket->flush();
|
socket->waitForBytesWritten( msecs );
|
||||||
return result;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 SingleApplicationPrivate::blockChecksum() const
|
quint16 SingleApplicationPrivate::blockChecksum()
|
||||||
{
|
{
|
||||||
#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(static_cast<const char*>(memory->constData()), offsetof(InstancesInfo, checksum)));
|
return qChecksum(
|
||||||
|
static_cast <const char *>( memory->data() ),
|
||||||
|
offsetof( InstancesInfo, checksum )
|
||||||
|
);
|
||||||
#else
|
#else
|
||||||
quint16 checksum = qChecksum(static_cast<const char*>(memory->constData()), offsetof(InstancesInfo, checksum));
|
#if TODO_LIST
|
||||||
|
#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() const
|
qint64 SingleApplicationPrivate::primaryPid()
|
||||||
{
|
{
|
||||||
qint64 pid;
|
qint64 pid;
|
||||||
|
|
||||||
memory->lock();
|
memory->lock();
|
||||||
auto *inst = static_cast<InstancesInfo*>( memory->data() );
|
InstancesInfo* 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, nextConnSocket, &QLocalSocket::deleteLater);
|
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
|
||||||
|
[nextConnSocket, this](){
|
||||||
|
connectionMap.remove(nextConnSocket);
|
||||||
|
nextConnSocket->deleteLater();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::destroyed,
|
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
||||||
[nextConnSocket, this](){
|
[nextConnSocket, this]() {
|
||||||
connectionMap.remove(nextConnSocket);
|
auto &info = connectionMap[nextConnSocket];
|
||||||
}
|
switch(info.stage) {
|
||||||
);
|
case StageHeader:
|
||||||
|
readInitMessageHeader(nextConnSocket);
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
break;
|
||||||
[nextConnSocket, this](){
|
case StageBody:
|
||||||
auto &info = connectionMap[nextConnSocket];
|
readInitMessageBody(nextConnSocket);
|
||||||
switch(info.stage){
|
break;
|
||||||
case StageHeader:
|
case StageConnected:
|
||||||
readInitMessageHeader(nextConnSocket);
|
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
|
||||||
break;
|
break;
|
||||||
case StageBody:
|
default:
|
||||||
readInitMessageBody(nextConnSocket);
|
break;
|
||||||
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)
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
|
||||||
const quint16 actualChecksum = qChecksum(QByteArray(msgBytes, static_cast<quint32>(msgBytes.length() - sizeof(quint16))));
|
const quint16 actualChecksum =
|
||||||
|
qChecksum(
|
||||||
|
msgBytes.constData(),
|
||||||
|
static_cast<quint32>( msgBytes.length() - sizeof( quint16 ) ) );
|
||||||
#else
|
#else
|
||||||
const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length() - sizeof(quint16)));
|
#if TODO_LIST
|
||||||
|
#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;
|
||||||
|
|
||||||
bool isValid = readStream.status() == QDataStream::Ok &&
|
if( !isValid ) {
|
||||||
QLatin1String(latin1Name) == blockServerName &&
|
sock->close();
|
||||||
msgChecksum == actualChecksum;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( !isValid ){
|
info.instanceId = instanceId;
|
||||||
sock->close();
|
info.stage = StageConnected;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.instanceId = instanceId;
|
if( connectionType == NewInstance ||
|
||||||
info.stage = StageConnected;
|
( connectionType == SecondaryInstance &&
|
||||||
|
options & SingleApplication::Mode::SecondaryNotification ) )
|
||||||
|
{
|
||||||
|
Q_EMIT q->instanceStarted();
|
||||||
|
}
|
||||||
|
|
||||||
if( connectionType == NewInstance ||
|
if (sock->bytesAvailable() > 0) {
|
||||||
( connectionType == SecondaryInstance &&
|
Q_EMIT this->slotDataAvailable( sock, instanceId );
|
||||||
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 - 2020
|
// Copyright (c) Itay Grudev 2015 - 2016
|
||||||
//
|
//
|
||||||
// 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,67 +38,62 @@
|
|||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
|
|
||||||
struct InstancesInfo {
|
struct InstancesInfo {
|
||||||
bool primary;
|
bool primary;
|
||||||
quint32 secondary;
|
quint32 secondary;
|
||||||
qint64 primaryPid;
|
qint64 primaryPid;
|
||||||
char primaryUser[128];
|
quint16 checksum;
|
||||||
quint16 checksum; // Must be the last field
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionInfo {
|
struct ConnectionInfo {
|
||||||
qint64 msgLen = 0;
|
explicit ConnectionInfo() :
|
||||||
quint32 instanceId = 0;
|
msgLen(0), instanceId(0), stage(0) {}
|
||||||
quint8 stage = 0;
|
qint64 msgLen;
|
||||||
|
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() override;
|
~SingleApplicationPrivate();
|
||||||
|
|
||||||
static QString getUsername();
|
void genBlockServerName();
|
||||||
void genBlockServerName();
|
void initializeMemoryBlock();
|
||||||
void initializeMemoryBlock() const;
|
void startPrimary();
|
||||||
void startPrimary();
|
void startSecondary();
|
||||||
void startSecondary();
|
void connectToPrimary(int msecs, ConnectionType connectionType );
|
||||||
bool connectToPrimary( int msecs, ConnectionType connectionType );
|
quint16 blockChecksum();
|
||||||
quint16 blockChecksum() const;
|
qint64 primaryPid();
|
||||||
qint64 primaryPid() const;
|
void readInitMessageHeader(QLocalSocket *socket);
|
||||||
QString primaryUser() const;
|
void readInitMessageBody(QLocalSocket *socket);
|
||||||
void readInitMessageHeader(QLocalSocket *socket);
|
|
||||||
void readInitMessageBody(QLocalSocket *socket);
|
SingleApplication *q_ptr;
|
||||||
static void randomSleep();
|
QSharedMemory *memory;
|
||||||
void addAppData(const QString &data);
|
QLocalSocket *socket;
|
||||||
QStringList appData() const;
|
QLocalServer *server;
|
||||||
|
quint32 instanceNumber;
|
||||||
SingleApplication *q_ptr;
|
QString blockServerName;
|
||||||
QSharedMemory *memory;
|
SingleApplication::Options options;
|
||||||
QLocalSocket *socket;
|
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
||||||
QLocalServer *server;
|
|
||||||
quint32 instanceNumber;
|
public Q_SLOTS:
|
||||||
QString blockServerName;
|
void slotConnectionEstablished();
|
||||||
SingleApplication::Options options;
|
void slotDataAvailable( QLocalSocket*, quint32 );
|
||||||
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
void slotClientConnectionClosed( QLocalSocket*, quint32 );
|
||||||
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.15",
|
"runtime-version": "5.14",
|
||||||
"sdk": "org.kde.Sdk",
|
"sdk": "org.kde.Sdk",
|
||||||
"command": "qelectrotech",
|
"command": "qelectrotech",
|
||||||
"rename-desktop-file": "qelectrotech.desktop",
|
"rename-desktop-file": "qelectrotech.desktop",
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# a KDE session forces the KDE Plasma platformtheme which is incompatible with QET
|
|
||||||
# unset the ENV vars in that case to prevent loading of the theme
|
|
||||||
if [ ! -z "$KDE_FULL_SESSION" ]; then
|
|
||||||
unset KDE_FULL_SESSION
|
|
||||||
fi
|
|
||||||
|
|
||||||
if echo "$XDG_CURRENT_DESKTOP" | grep -q KDE; then
|
|
||||||
unset XDG_CURRENT_DESKTOP
|
|
||||||
fi
|
|
||||||
|
|
||||||
# migrate .qet directory from SNAP_USER_DATA to SNAP_USER_COMMON
|
# migrate .qet directory from SNAP_USER_DATA to SNAP_USER_COMMON
|
||||||
from="$SNAP_USER_DATA/.qet"
|
from="$SNAP_USER_DATA/.qet"
|
||||||
to="$SNAP_USER_COMMON/.qet"
|
to="$SNAP_USER_COMMON/.qet"
|
||||||
@@ -23,12 +13,4 @@ fi
|
|||||||
mkdir -p "$HOME/.qet"
|
mkdir -p "$HOME/.qet"
|
||||||
ln -snf "$SNAP/bin/DXFtoQET" "$HOME/.qet/DXFtoQET"
|
ln -snf "$SNAP/bin/DXFtoQET" "$HOME/.qet/DXFtoQET"
|
||||||
|
|
||||||
# start desktop portal. Open & save dialogs might fail if it is not running
|
|
||||||
dbus-send --print-reply \
|
|
||||||
--dest=org.freedesktop.DBus \
|
|
||||||
/org/freedesktop/DBus \
|
|
||||||
org.freedesktop.DBus.StartServiceByName \
|
|
||||||
string:org.freedesktop.portal.Desktop \
|
|
||||||
uint32:0
|
|
||||||
|
|
||||||
exec "${@}"
|
exec "${@}"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: qelectrotech
|
name: qelectrotech
|
||||||
title: QElectroTech
|
title: QElectroTech
|
||||||
base: core18
|
base: core20
|
||||||
adopt-info: qelectrotech
|
version: "0.8.0"
|
||||||
license: GPL-2.0
|
license: GPL-2.0
|
||||||
summary: Electrical diagram editor
|
summary: Electrical diagram editor
|
||||||
description: |
|
description: |
|
||||||
@@ -10,10 +10,7 @@ description: |
|
|||||||
|
|
||||||
grade: stable
|
grade: stable
|
||||||
confinement: strict
|
confinement: strict
|
||||||
|
compression: lzo
|
||||||
architectures:
|
|
||||||
- build-on: amd64
|
|
||||||
run-on: amd64
|
|
||||||
|
|
||||||
layout:
|
layout:
|
||||||
/usr/local/share/qelectrotech:
|
/usr/local/share/qelectrotech:
|
||||||
@@ -30,15 +27,14 @@ apps:
|
|||||||
extensions: [kde-neon]
|
extensions: [kde-neon]
|
||||||
plugs: &plugs [opengl, unity7, home, removable-media, gsettings, network, cups-control]
|
plugs: &plugs [opengl, unity7, home, removable-media, gsettings, network, cups-control]
|
||||||
environment: &env
|
environment: &env
|
||||||
__EGL_VENDOR_LIBRARY_DIRS: $SNAP/kf5/usr/share/glvnd/egl_vendor.d:$SNAP/usr/share/glvnd/egl_vendor.d
|
|
||||||
TCL_LIBRARY: $SNAP/usr/share/tcltk/tcl8.6
|
TCL_LIBRARY: $SNAP/usr/share/tcltk/tcl8.6
|
||||||
QT_QPA_PLATFORMTHEME: gtk3
|
|
||||||
QT_AUTO_SCREEN_SCALE_FACTOR: 1
|
|
||||||
HOME: $SNAP_USER_COMMON
|
HOME: $SNAP_USER_COMMON
|
||||||
PYTHONPATH: $SNAP:$SNAP/lib/python3.6/site-packages:$SNAP/usr/lib/python3.6:$SNAP/usr/lib/python3.6/lib-dynload
|
PYTHONPATH: $SNAP:$SNAP/lib/python3.8/site-packages:$SNAP/usr/lib/python3.8:$SNAP/usr/lib/python3.8/lib-dynload
|
||||||
|
|
||||||
qet-tb-generator:
|
qet-tb-generator:
|
||||||
command: bin/qelectrotech-launch $SNAP/bin/qet_tb_generator
|
command: bin/qet_tb_generator
|
||||||
|
command-chain:
|
||||||
|
- bin/qelectrotech-launch
|
||||||
extensions: [kde-neon]
|
extensions: [kde-neon]
|
||||||
plugs: *plugs
|
plugs: *plugs
|
||||||
environment: *env
|
environment: *env
|
||||||
@@ -58,8 +54,8 @@ parts:
|
|||||||
|
|
||||||
qet-tb-generator:
|
qet-tb-generator:
|
||||||
plugin: python
|
plugin: python
|
||||||
python-version: python3
|
source: https://github.com/raulroda/qet_tb_generator-plugin.git
|
||||||
source: https://github.com/qelectrotech/qet_tb_generator.git
|
python-packages: [PySimpleGUI]
|
||||||
stage-packages:
|
stage-packages:
|
||||||
- python3-lxml
|
- python3-lxml
|
||||||
- python3-tk
|
- python3-tk
|
||||||
@@ -68,15 +64,15 @@ parts:
|
|||||||
kde-sdk-setup:
|
kde-sdk-setup:
|
||||||
plugin: nil
|
plugin: nil
|
||||||
build-snaps:
|
build-snaps:
|
||||||
- kde-frameworks-5-core18-sdk
|
- kde-frameworks-5-qt-5-15-3-core20-sdk
|
||||||
build-packages:
|
build-packages:
|
||||||
- g++
|
- g++
|
||||||
- mesa-common-dev
|
- mesa-common-dev
|
||||||
- libglvnd-dev
|
- libglvnd-dev
|
||||||
- rsync
|
- rsync
|
||||||
override-build: |
|
override-build: |
|
||||||
rsync -a --ignore-existing /snap/kde-frameworks-5-core18-sdk/current/ /
|
rsync -a --ignore-existing /snap/kde-frameworks-5-qt-5-15-3-core20-sdk/current/ /
|
||||||
|
|
||||||
dxf-to-qet:
|
dxf-to-qet:
|
||||||
after: [kde-sdk-setup]
|
after: [kde-sdk-setup]
|
||||||
plugin: nil
|
plugin: nil
|
||||||
@@ -91,19 +87,15 @@ parts:
|
|||||||
after: [kde-sdk-setup]
|
after: [kde-sdk-setup]
|
||||||
plugin: nil
|
plugin: nil
|
||||||
source: .
|
source: .
|
||||||
stage-packages: [ git, sqlite3 ]
|
stage-packages: [ git, sqlite3, xdg-user-dirs ]
|
||||||
build-packages:
|
build-packages:
|
||||||
- git
|
- git
|
||||||
- libsqlite3-dev
|
- libsqlite3-dev
|
||||||
override-pull: |
|
|
||||||
snapcraftctl pull
|
|
||||||
snap_version=$(git describe --dirty)
|
|
||||||
modified_displayed_version=$snap_version".snap"
|
|
||||||
sed -i -E "s|const QString displayedVersion =.*|const QString displayedVersion =\"$modified_displayed_version\";|" sources/qet.h
|
|
||||||
snapcraftctl set-version "$snap_version"
|
|
||||||
override-build: |
|
override-build: |
|
||||||
|
modified_displayed_version="${SNAPCRAFT_PROJECT_VERSION}.snap"
|
||||||
|
sed -i -E "s|const QString displayedVersion =.*|const QString displayedVersion =\"$modified_displayed_version\";|" sources/qet.h
|
||||||
qmake "$SNAPCRAFT_PART_SRC/qelectrotech.pro"
|
qmake "$SNAPCRAFT_PART_SRC/qelectrotech.pro"
|
||||||
make -j$(nproc)
|
make -j${SNAPCRAFT_PARALLEL_BUILD_COUNT}
|
||||||
make install INSTALL_ROOT="$SNAPCRAFT_PART_INSTALL"
|
make install INSTALL_ROOT="$SNAPCRAFT_PART_INSTALL"
|
||||||
override-stage: |
|
override-stage: |
|
||||||
snapcraftctl stage
|
snapcraftctl stage
|
||||||
@@ -114,11 +106,14 @@ parts:
|
|||||||
cleanup:
|
cleanup:
|
||||||
after: [qelectrotech, dxf-to-qet, qet-tb-generator]
|
after: [qelectrotech, dxf-to-qet, qet-tb-generator]
|
||||||
plugin: nil
|
plugin: nil
|
||||||
build-snaps: [core18, kde-frameworks-5-core18]
|
build-snaps: [kde-frameworks-5-qt-5-15-3-core20]
|
||||||
override-prime: |
|
override-prime: |
|
||||||
# Remove all files from snap that are already included in the base snap or in
|
|
||||||
# any connected content snaps
|
|
||||||
set -eux
|
set -eux
|
||||||
for snap in "core18" "kde-frameworks-5-core18"; do # List all content-snaps and base snaps you're using here
|
for snap in "kde-frameworks-5-qt-5-15-3-core20"; do # List all content-snaps you're using here
|
||||||
cd "/snap/$snap/current" && find . -type f,l -exec rm -f "$SNAPCRAFT_PRIME/{}" \;
|
cd "/snap/$snap/current" && find . -type f,l -exec rm -f "$SNAPCRAFT_PRIME/{}" "$SNAPCRAFT_PRIME/usr/{}" \;
|
||||||
done
|
done
|
||||||
|
for cruft in bug lintian man; do
|
||||||
|
rm -rf $SNAPCRAFT_PRIME/usr/share/$cruft
|
||||||
|
done
|
||||||
|
find $SNAPCRAFT_PRIME/usr/share/doc/ -type f -not -name 'copyright' -delete
|
||||||
|
find $SNAPCRAFT_PRIME/usr/share -type d -empty -delete
|
||||||
|
|||||||
@@ -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.4)
|
GIT_TAG v1.11.1)
|
||||||
|
|
||||||
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.2.0)
|
GIT_TAG v3.1.5)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(SingleApplication)
|
FetchContent_MakeAvailable(SingleApplication)
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ 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
|
||||||
@@ -262,8 +260,12 @@ 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
|
||||||
@@ -318,12 +320,8 @@ 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
|
||||||
@@ -373,8 +371,6 @@ 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
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="52" version="0.51" hotspot_x="56" link_type="master" width="70" type="element" height="100">
|
<definition hotspot_y="52" version="0.51" hotspot_x="56" link_type="simple" width="70" type="element" height="100">
|
||||||
<uuid uuid="{2d6c186b-0578-4682-90c9-f77843432e9f}"/>
|
<uuid uuid="{2d6c186b-0578-4682-90c9-f77843432e9f}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="cs">Motorový spouštěč 1P+N</name>
|
<name lang="cs">Motorový spouštěč 1P+N</name>
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
||||||
<name lang="hu">Motorvédő kapcsoló 1 pólusú GV</name>
|
<name lang="hu">Motorvédő kapcsoló 1 pólusú GV</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<polygon x1="0" y1="14" x5="0" y4="4" y5="4" x6="0" y7="-25" x2="0" y6="-6" y2="10" y3="10" x7="-7" antialias="true" x3="5" closed="false" x4="5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
<polygon x1="0" y1="14" x5="0" y4="4" y5="4" x6="0" y7="-25" x2="0" y6="-6" y2="10" y3="10" x7="-7" antialias="true" x3="5" closed="false" x4="5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="52" width="70" version="0.51" type="element" height="100" hotspot_x="56" link_type="master">
|
<definition hotspot_y="52" width="70" version="0.51" type="element" height="100" hotspot_x="56" link_type="simple">
|
||||||
<uuid uuid="{ec5fa3cd-6769-4a35-aaa9-6bc5ba4fc779}"/>
|
<uuid uuid="{ec5fa3cd-6769-4a35-aaa9-6bc5ba4fc779}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="fr">Disjoncteur Magnéto-thermique GV 2P</name>
|
<name lang="fr">Disjoncteur Magnéto-thermique GV 2P</name>
|
||||||
@@ -8,9 +8,6 @@
|
|||||||
<name lang="cs">Motorový spouštěč 2P</name>
|
<name lang="cs">Motorový spouštěč 2P</name>
|
||||||
<name lang="hu">Motorvédő kapcsoló 2 pólusú GV</name>
|
<name lang="hu">Motorvédő kapcsoló 2 pólusú GV</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<polygon y2="10" x3="-15" y4="4" x2="-20" y3="10" x5="-20" style="line-style:normal;line-weight:normal;filling:none;color:black" x1="-20" x4="-15" closed="false" y1="14" y6="-6" x7="-27" y5="4" antialias="true" y7="-25" x6="-20"/>
|
<polygon y2="10" x3="-15" y4="4" x2="-20" y3="10" x5="-20" style="line-style:normal;line-weight:normal;filling:none;color:black" x1="-20" x4="-15" closed="false" y1="14" y6="-6" x7="-27" y5="4" antialias="true" y7="-25" x6="-20"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="52" version="0.51" hotspot_x="56" link_type="master" width="110" type="element" height="100">
|
<definition hotspot_y="52" version="0.51" hotspot_x="56" link_type="simple" width="110" type="element" height="100">
|
||||||
<uuid uuid="{2424a938-847f-447f-a4ad-d9b6ef730fd9}"/>
|
<uuid uuid="{2424a938-847f-447f-a4ad-d9b6ef730fd9}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="de">Motorschutzschalter</name>
|
<name lang="de">Motorschutzschalter</name>
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
||||||
<name lang="hu">Motorvédő kapcsoló 3F + N pólusú</name>
|
<name lang="hu">Motorvédő kapcsoló 3F + N pólusú</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<line end1="none" x1="40" y1="39" x2="40" length1="1.5" y2="28" antialias="false" end2="none" length2="1.5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
<line end1="none" x1="40" y1="39" x2="40" length1="1.5" y2="28" antialias="false" end2="none" length2="1.5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="50" width="110" version="0.51" type="element" height="100" hotspot_x="56" link_type="master">
|
<definition hotspot_y="50" width="110" version="0.51" type="element" height="100" hotspot_x="56" link_type="simple">
|
||||||
<uuid uuid="{686e19c6-6bce-4ced-8c01-2d7f58a78386}"/>
|
<uuid uuid="{686e19c6-6bce-4ced-8c01-2d7f58a78386}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="el">Θερμομαγνητικό</name>
|
<name lang="el">Θερμομαγνητικό</name>
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
<name lang="de">Motorschutzschalter</name>
|
<name lang="de">Motorschutzschalter</name>
|
||||||
<name lang="hu">Motorvédő kapcsoló 4 pólusú GV</name>
|
<name lang="hu">Motorvédő kapcsoló 4 pólusú GV</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<line y2="28" end1="none" length2="1.5" x2="40" style="line-style:normal;line-weight:normal;filling:none;color:black" x1="40" length1="1.5" y1="39" end2="none" antialias="false"/>
|
<line y2="28" end1="none" length2="1.5" x2="40" style="line-style:normal;line-weight:normal;filling:none;color:black" x1="40" length1="1.5" y1="39" end2="none" antialias="false"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition type="element" link_type="master" hotspot_x="31" hotspot_y="4" version="0.5" width="90" height="70">
|
<definition type="element" link_type="simple" hotspot_x="31" hotspot_y="4" version="0.5" width="90" height="70">
|
||||||
<uuid uuid="{98ADF831-42F0-4EDE-9267-6733EEBEAF62}"/><names>
|
<uuid uuid="{98ADF831-42F0-4EDE-9267-6733EEBEAF62}"/><names>
|
||||||
<name lang="en">Motor circuit breaker</name>
|
<name lang="en">Motor circuit breaker</name>
|
||||||
<name lang="es">Disyuntor termico magnetico 3P mando manual con auto retorno y boton de desenclave</name>
|
<name lang="es">Disyuntor termico magnetico 3P mando manual con auto retorno y boton de desenclave</name>
|
||||||
@@ -10,9 +10,6 @@
|
|||||||
<name lang="pl">Wyłącznik silnikowy</name>
|
<name lang="pl">Wyłącznik silnikowy</name>
|
||||||
<name lang="hu">Motorvédő kapcsoló 3 pólusú</name>
|
<name lang="hu">Motorvédő kapcsoló 3 pólusú</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations>Author: The QElectroTech team
|
<informations>Author: The QElectroTech team
|
||||||
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
|
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
|
||||||
<description>
|
<description>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition type="element" link_type="master" hotspot_x="33" hotspot_y="5" version="0.5" width="110" height="70">
|
<definition type="element" link_type="simple" hotspot_x="33" hotspot_y="5" version="0.5" width="110" height="70">
|
||||||
<uuid uuid="{C33FE39E-B2EE-4EC0-BC3F-4EB76E9BCEA0}"/><names>
|
<uuid uuid="{C33FE39E-B2EE-4EC0-BC3F-4EB76E9BCEA0}"/><names>
|
||||||
<name lang="en">Motor circuit breaker with neutral</name>
|
<name lang="en">Motor circuit breaker with neutral</name>
|
||||||
<name lang="es">Disyuntor termico magnetico 3P+N mando manual con auto retorno y boton de desenclave</name>
|
<name lang="es">Disyuntor termico magnetico 3P+N mando manual con auto retorno y boton de desenclave</name>
|
||||||
@@ -10,9 +10,6 @@
|
|||||||
<name lang="pl">Wyłącznik silnikowy</name>
|
<name lang="pl">Wyłącznik silnikowy</name>
|
||||||
<name lang="hu">Motorvédő kapcsoló 3F + N pólusú</name>
|
<name lang="hu">Motorvédő kapcsoló 3F + N pólusú</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations>Author: The QElectroTech team
|
<informations>Author: The QElectroTech team
|
||||||
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
|
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
|
||||||
<description>
|
<description>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="master" width="70" type="element" height="110">
|
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="simple" width="70" type="element" height="110">
|
||||||
<uuid uuid="{68830151-5901-40f6-b94d-dc68b85165a2}"/>
|
<uuid uuid="{68830151-5901-40f6-b94d-dc68b85165a2}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="fr">Disjoncteur differentiel 1P+N</name>
|
<name lang="fr">Disjoncteur differentiel 1P+N</name>
|
||||||
@@ -8,9 +8,6 @@
|
|||||||
<name lang="cs">Jističochránič 2P</name>
|
<name lang="cs">Jističochránič 2P</name>
|
||||||
<name lang="hu">Differenciál-védőkapcsoló 1P+N termikus és zárlatvédelemmel</name>
|
<name lang="hu">Differenciál-védőkapcsoló 1P+N termikus és zárlatvédelemmel</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<line end1="none" x1="-29.6203" y1="28" x2="10" length1="1.5" y2="28" antialias="false" end2="none" length2="1.5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
<line end1="none" x1="-29.6203" y1="28" x2="10" length1="1.5" y2="28" antialias="false" end2="none" length2="1.5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="master" width="110" type="element" height="110">
|
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="simple" width="110" type="element" height="110">
|
||||||
<uuid uuid="{3fa48846-98c0-43e1-8a96-330d4dc11ceb}"/>
|
<uuid uuid="{3fa48846-98c0-43e1-8a96-330d4dc11ceb}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="cs">Jističochránič 3P+N</name>
|
<name lang="cs">Jističochránič 3P+N</name>
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
||||||
<name lang="hu">Differenciál-védőkapcsoló 3P+N termikus és zárlatvédelemmel</name>
|
<name lang="hu">Differenciál-védőkapcsoló 3P+N termikus és zárlatvédelemmel</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<line end1="none" x1="-29.6203" y1="28" x2="49.5887" length1="1.5" y2="28" antialias="false" end2="none" length2="1.5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
<line end1="none" x1="-29.6203" y1="28" x2="49.5887" length1="1.5" y2="28" antialias="false" end2="none" length2="1.5" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="master" width="70" type="element" height="110">
|
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="simple" width="70" type="element" height="110">
|
||||||
<uuid uuid="{20f65431-6f1f-4e09-9c73-68a1431c40a1}"/>
|
<uuid uuid="{20f65431-6f1f-4e09-9c73-68a1431c40a1}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="fr">Disjoncteur differentiel 2P</name>
|
<name lang="fr">Disjoncteur differentiel 2P</name>
|
||||||
@@ -8,9 +8,6 @@
|
|||||||
<name lang="cs">Jističochránič 2P</name>
|
<name lang="cs">Jističochránič 2P</name>
|
||||||
<name lang="hu">Differenciál-védőkapcsoló 2P termikus és zárlatvédelemmel</name>
|
<name lang="hu">Differenciál-védőkapcsoló 2P termikus és zárlatvédelemmel</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<polygon x1="-20" y1="14" x5="-20" y4="4" y5="4" x6="-20" y7="-25" x2="-20" y6="-6" y2="10" y3="10" x7="-27" antialias="true" x3="-15" closed="false" x4="-15" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
<polygon x1="-20" y1="14" x5="-20" y4="4" y5="4" x6="-20" y7="-25" x2="-20" y6="-6" y2="10" y3="10" x7="-27" antialias="true" x3="-15" closed="false" x4="-15" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="master" width="90" type="element" height="110">
|
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="simple" width="90" type="element" height="110">
|
||||||
<uuid uuid="{1e746e43-1906-4ea0-99a6-261e3c862dba}"/>
|
<uuid uuid="{1e746e43-1906-4ea0-99a6-261e3c862dba}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="cs">Jističochránič 3P</name>
|
<name lang="cs">Jističochránič 3P</name>
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
||||||
<name lang="hu">Differenciál-védőkapcsoló 3P termikus és zárlatvédelemmel</name>
|
<name lang="hu">Differenciál-védőkapcsoló 3P termikus és zárlatvédelemmel</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<text text="I>" size="9" y="25" x="-24"/>
|
<text text="I>" size="9" y="25" x="-24"/>
|
||||||
|
|||||||
+1
-4
@@ -1,4 +1,4 @@
|
|||||||
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="master" width="110" type="element" height="110">
|
<definition hotspot_y="50" version="0.51" hotspot_x="56" link_type="simple" width="110" type="element" height="110">
|
||||||
<uuid uuid="{fee3faef-5f4a-4a0b-bf0e-b6e93d9f9425}"/>
|
<uuid uuid="{fee3faef-5f4a-4a0b-bf0e-b6e93d9f9425}"/>
|
||||||
<names>
|
<names>
|
||||||
<name lang="de">Motorschutzschalter</name>
|
<name lang="de">Motorschutzschalter</name>
|
||||||
@@ -12,9 +12,6 @@
|
|||||||
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
|
||||||
<name lang="hu">Differenciál-védőkapcsoló 4P termikus és zárlatvédelemmel</name>
|
<name lang="hu">Differenciál-védőkapcsoló 4P termikus és zárlatvédelemmel</name>
|
||||||
</names>
|
</names>
|
||||||
<kindInformations>
|
|
||||||
<kindInformation name="type" show="1">protection</kindInformation>
|
|
||||||
</kindInformations>
|
|
||||||
<informations></informations>
|
<informations></informations>
|
||||||
<description>
|
<description>
|
||||||
<polygon x1="-20" y1="14" x5="-20" y4="4" y5="4" x6="-20" y7="-25" x2="-20" y6="-6" y2="10" y3="10" x7="-27" antialias="true" x3="-15" closed="false" x4="-15" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
<polygon x1="-20" y1="14" x5="-20" y4="4" y5="4" x6="-20" y7="-25" x2="-20" y6="-6" y2="10" y3="10" x7="-27" antialias="true" x3="-15" closed="false" x4="-15" style="line-style:normal;line-weight:normal;filling:none;color:black"/>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 112 KiB |
+583
-712
File diff suppressed because it is too large
Load Diff
+591
-720
File diff suppressed because it is too large
Load Diff
+583
-712
File diff suppressed because it is too large
Load Diff
+592
-723
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+595
-723
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+874
-1006
File diff suppressed because it is too large
Load Diff
+590
-719
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+590
-721
File diff suppressed because it is too large
Load Diff
+585
-714
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+579
-708
File diff suppressed because it is too large
Load Diff
+582
-711
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+587
-718
File diff suppressed because it is too large
Load Diff
+594
-723
File diff suppressed because it is too large
Load Diff
+583
-712
File diff suppressed because it is too large
Load Diff
+579
-708
File diff suppressed because it is too large
Load Diff
+583
-712
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+591
-722
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+600
-732
File diff suppressed because it is too large
Load Diff
+588
-720
File diff suppressed because it is too large
Load Diff
+585
-714
File diff suppressed because it is too large
Load Diff
+583
-712
File diff suppressed because it is too large
Load Diff
+583
-712
File diff suppressed because it is too large
Load Diff
+579
-708
File diff suppressed because it is too large
Load Diff
+579
-708
File diff suppressed because it is too large
Load Diff
+579
-708
File diff suppressed because it is too large
Load Diff
+583
-712
File diff suppressed because it is too large
Load Diff
+579
-708
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "elementscollectionwidget.h"
|
#include "elementscollectionwidget.h"
|
||||||
|
|
||||||
#include "../editor/ui/qetelementeditor.h"
|
#include "../editor/qetelementeditor.h"
|
||||||
#include "../elementscategoryeditor.h"
|
#include "../elementscategoryeditor.h"
|
||||||
#include "../newelementwizard.h"
|
#include "../newelementwizard.h"
|
||||||
#include "../qetapp.h"
|
#include "../qetapp.h"
|
||||||
@@ -38,9 +38,6 @@
|
|||||||
#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,6 +368,14 @@ 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,6 +222,11 @@ 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);
|
||||||
|
|||||||
@@ -501,7 +501,7 @@ void DiagramView::mousePressEvent(QMouseEvent *e)
|
|||||||
*/
|
*/
|
||||||
void DiagramView::mouseMoveEvent(QMouseEvent *e)
|
void DiagramView::mouseMoveEvent(QMouseEvent *e)
|
||||||
{
|
{
|
||||||
setToolTip(tr("X: %1 Y: %2").arg(e->pos().x()).arg(e->pos().y()));
|
setToolTip(tr("(Dev) X: %1 Y: %2").arg(e->pos().x()).arg(e->pos().y()));
|
||||||
if (m_event_interface && m_event_interface->mouseMoveEvent(e)) return;
|
if (m_event_interface && m_event_interface->mouseMoveEvent(e)) return;
|
||||||
|
|
||||||
// Drag the view
|
// Drag the view
|
||||||
|
|||||||
@@ -282,17 +282,13 @@ ChangeNamesCommand::~ChangeNamesCommand()
|
|||||||
/// Annule le changement
|
/// Annule le changement
|
||||||
void ChangeNamesCommand::undo()
|
void ChangeNamesCommand::undo()
|
||||||
{
|
{
|
||||||
auto data = m_scene->elementData();
|
m_scene -> setNames(names_before);
|
||||||
data.m_names_list = names_before;
|
|
||||||
m_scene->setElementData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Refait le changement
|
/// Refait le changement
|
||||||
void ChangeNamesCommand::redo()
|
void ChangeNamesCommand::redo()
|
||||||
{
|
{
|
||||||
auto data = m_scene->elementData();
|
m_scene -> setNames(names_after);
|
||||||
data.m_names_list = names_after;
|
|
||||||
m_scene->setElementData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -457,17 +453,13 @@ 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()
|
||||||
{
|
{
|
||||||
auto data = m_scene->elementData();
|
m_scene -> setInformations(old_informations_);
|
||||||
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()
|
||||||
{
|
{
|
||||||
auto data = m_scene->elementData();
|
m_scene -> setInformations(new_informations_);
|
||||||
data.m_drawing_information = new_informations_;
|
|
||||||
m_scene->setElementData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -580,32 +572,45 @@ 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 changeElementDataCommand::changeElementDataCommand
|
@brief ChangePropertiesCommand::ChangePropertiesCommand
|
||||||
* 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 old_data : old data
|
@param type : new type of element.
|
||||||
* @param new_data : new data
|
@param info
|
||||||
* @param parent : parent undo command
|
@param elmt_info : new info about type.
|
||||||
*/
|
@param parent : parent undo
|
||||||
changeElementDataCommand::changeElementDataCommand(ElementScene *scene,
|
*/
|
||||||
ElementData old_data,
|
ChangePropertiesCommand::ChangePropertiesCommand(
|
||||||
ElementData new_data,
|
ElementScene *scene,
|
||||||
QUndoCommand *parent) :
|
const QString& type,
|
||||||
ElementEditionCommand(scene, nullptr, parent),
|
const DiagramContext& info,
|
||||||
m_old(old_data),
|
const DiagramContext& elmt_info,
|
||||||
m_new(new_data)
|
QUndoCommand *parent) :
|
||||||
|
ElementEditionCommand(scene, nullptr, parent)
|
||||||
{
|
{
|
||||||
setText(QObject::tr("Modifier les propriétées de l'élément"));
|
m_type << scene->m_elmt_type << type;
|
||||||
|
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"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeElementDataCommand::undo() {
|
ChangePropertiesCommand::~ChangePropertiesCommand()
|
||||||
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 changeElementDataCommand::redo() {
|
void ChangePropertiesCommand::redo()
|
||||||
m_scene->setElementData(m_new);
|
{
|
||||||
QUndoCommand::redo();
|
m_scene->m_elmt_type = m_type.last();
|
||||||
|
m_scene->m_elmt_kindInfo = m_kind_info.last();
|
||||||
|
m_scene->setElementInfo(m_elmt_info.last());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -262,21 +262,23 @@ class ScalePartsCommand : public ElementEditionCommand {
|
|||||||
bool first_redo;
|
bool first_redo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class changeElementDataCommand : public ElementEditionCommand
|
class ChangePropertiesCommand : public ElementEditionCommand {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
changeElementDataCommand(ElementScene *scene,
|
ChangePropertiesCommand (
|
||||||
ElementData old_data,
|
ElementScene *scene,
|
||||||
ElementData new_data,
|
const QString& type,
|
||||||
QUndoCommand *parent = nullptr);
|
const DiagramContext& info,
|
||||||
~changeElementDataCommand() override {}
|
const DiagramContext& elmt_info,
|
||||||
|
QUndoCommand *parent=nullptr);
|
||||||
|
~ChangePropertiesCommand () override;
|
||||||
|
|
||||||
void undo() override;
|
void undo() override;
|
||||||
void redo() override;
|
void redo() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ElementData m_old,
|
QList <QString> m_type;
|
||||||
m_new;
|
QList <DiagramContext> m_kind_info;
|
||||||
|
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 "ui/qetelementeditor.h"
|
#include "qetelementeditor.h"
|
||||||
#include "editorcommands.h"
|
#include "editorcommands.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+105
-55
@@ -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 "ui/qetelementeditor.h"
|
#include "qetelementeditor.h"
|
||||||
#include "ui/elementpropertieseditorwidget.h"
|
#include "ui/elementpropertieseditorwidget.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -70,25 +71,7 @@ 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -454,7 +437,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_element_data.typeToString(m_element_data.m_type));
|
root.setAttribute("link_type", m_elmt_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");
|
||||||
@@ -462,29 +445,29 @@ const QDomDocument ElementScene::toXml(bool all_parts)
|
|||||||
root.appendChild(uuid);
|
root.appendChild(uuid);
|
||||||
|
|
||||||
//names of element
|
//names of element
|
||||||
root.appendChild(m_element_data.m_names_list.toXml(xml_document));
|
root.appendChild(m_names_list.toXml(xml_document));
|
||||||
|
|
||||||
auto type_ = m_element_data.m_type;
|
if (m_elmt_type == "slave" || m_elmt_type == "master")
|
||||||
if (type_ == ElementData::Slave ||
|
|
||||||
type_ == ElementData::Master ||
|
|
||||||
type_ == ElementData::Terminale)
|
|
||||||
{
|
{
|
||||||
root.appendChild(m_element_data.kindInfoToXml(xml_document));
|
QDomElement kindInfo = xml_document.createElement("kindInformations");
|
||||||
|
m_elmt_kindInfo.toXml(kindInfo, "kindInformation");
|
||||||
|
root.appendChild(kindInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type_ == ElementData::Simple ||
|
if(
|
||||||
type_ == ElementData::Master ||
|
m_elmt_type == "simple"
|
||||||
type_ == ElementData::Terminale)
|
|| m_elmt_type == "master"
|
||||||
|
|| m_elmt_type == "terminal")
|
||||||
{
|
{
|
||||||
QDomElement element_info = xml_document.createElement("elementInformations");
|
QDomElement element_info = xml_document.createElement("elementInformations");
|
||||||
m_element_data.m_informations.toXml(element_info, "elementInformation");
|
m_elmt_information.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(m_element_data.m_drawing_information));
|
informations_element.appendChild(xml_document.createTextNode(informations()));
|
||||||
|
|
||||||
QDomElement description = xml_document.createElement("description");
|
QDomElement description = xml_document.createElement("description");
|
||||||
|
|
||||||
@@ -562,16 +545,9 @@ 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)
|
||||||
@@ -723,6 +699,19 @@ 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,
|
||||||
@@ -844,7 +833,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(m_element_data.m_drawing_information);
|
text_field -> setPlainText(informations());
|
||||||
text_field -> setReadOnly(is_read_only);
|
text_field -> setReadOnly(is_read_only);
|
||||||
dialog_layout -> addWidget(text_field);
|
dialog_layout -> addWidget(text_field);
|
||||||
|
|
||||||
@@ -862,10 +851,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 != m_element_data.m_drawing_information)
|
if (new_infos != informations())
|
||||||
{
|
{
|
||||||
undoStack().push(new ChangeInformationsCommand(
|
undoStack().push(new ChangeInformationsCommand(
|
||||||
this, m_element_data.m_drawing_information, new_infos));
|
this, informations(), new_infos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -876,15 +865,20 @@ void ElementScene::slot_editAuthorInformations()
|
|||||||
*/
|
*/
|
||||||
void ElementScene::slot_editProperties()
|
void ElementScene::slot_editProperties()
|
||||||
{
|
{
|
||||||
ElementPropertiesEditorWidget epew(m_element_data);
|
QString type = m_elmt_type;
|
||||||
|
DiagramContext kind_info = m_elmt_kindInfo;
|
||||||
|
DiagramContext elmt_info = m_elmt_information;
|
||||||
|
|
||||||
|
ElementPropertiesEditorWidget epew(type, kind_info, elmt_info);
|
||||||
epew.exec();
|
epew.exec();
|
||||||
|
|
||||||
if (m_element_data != epew.editedData())
|
if (type != m_elmt_type ||
|
||||||
{
|
kind_info != m_elmt_kindInfo ||
|
||||||
undoStack().push(new changeElementDataCommand(this,
|
elmt_info != m_elmt_information)
|
||||||
m_element_data,
|
undoStack().push(new ChangePropertiesCommand(this,
|
||||||
epew.editedData()));
|
type,
|
||||||
}
|
kind_info,
|
||||||
|
elmt_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -904,15 +898,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_element_data.m_names_list);
|
nlw_->setNames(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_element_data. m_names_list) {
|
if (new_names != m_names_list) {
|
||||||
undoStack().push(new ChangeNamesCommand(this,
|
undoStack().push(new ChangeNamesCommand(this,
|
||||||
m_element_data.m_names_list,
|
m_names_list,
|
||||||
new_names));
|
new_names));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1093,6 +1087,62 @@ 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,7 +21,6 @@
|
|||||||
#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>
|
||||||
@@ -66,7 +65,11 @@ class ElementScene : public QGraphicsScene
|
|||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
private:
|
private:
|
||||||
ElementData m_element_data; ///ElementData. Actualy in transition with old data storage
|
NamesList m_names_list; /// List of localized names
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -87,20 +90,21 @@ 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 &,
|
||||||
@@ -124,6 +128,7 @@ 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;
|
||||||
@@ -132,10 +137,12 @@ 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 &);
|
||||||
@@ -173,4 +180,39 @@ 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 "ui/qetelementeditor.h"
|
#include "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 "../ui/qetelementeditor.h"
|
#include "../qetelementeditor.h"
|
||||||
|
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|||||||
@@ -18,8 +18,7 @@
|
|||||||
#include "eseventinterface.h"
|
#include "eseventinterface.h"
|
||||||
|
|
||||||
#include "../elementscene.h"
|
#include "../elementscene.h"
|
||||||
#include "../ui/qetelementeditor.h"
|
#include "../qetelementeditor.h"
|
||||||
#include "../elementview.h"
|
|
||||||
|
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
|
||||||
@@ -41,7 +40,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->elementView()->setDragMode(QGraphicsView::NoDrag);
|
m_editor->slot_setNoDragToView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -54,31 +53,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->elementView()->setDragMode(QGraphicsView::RubberBandDrag);
|
m_editor->slot_setRubberBandToView();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +97,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,6 +1264,24 @@ 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,6 +309,8 @@ 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,8 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "customelementpart.h"
|
#include "customelementpart.h"
|
||||||
|
|
||||||
#include "../ui/qetelementeditor.h"
|
#include "../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()->elementData().m_informations.value(m_info_name).toString());
|
setPlainText(elementScene() -> elementInformation().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()->elementData().m_informations));
|
setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementScene() -> elementInformation()));
|
||||||
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()->elementData().m_informations.value(m_info_name).toString());
|
setPlainText(elementScene() -> elementInformation().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()->elementData().m_informations));
|
m_composite_text, elementScene() -> elementInformation()));
|
||||||
}
|
}
|
||||||
|
|
||||||
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 "../ui/qetelementeditor.h"
|
#include "../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 -> m_second_point);
|
painter -> drawLine(QPointF(0.0, 0.0), d -> 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 -> m_second_point);
|
shape.lineTo(d -> 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 -> m_second_point);
|
QRectF br(QPointF(0, 0), d -> second_point);
|
||||||
br = br.normalized();
|
br = br.normalized();
|
||||||
|
|
||||||
qreal adjust = (SHADOWS_HEIGHT + 1) / 2;
|
qreal adjust = (SHADOWS_HEIGHT + 1) / 2;
|
||||||
@@ -161,20 +161,6 @@ 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();
|
||||||
@@ -188,10 +174,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 -> m_second_point = QPointF(0.0, ts); break;
|
case Qet::North: d -> second_point = QPointF(0.0, ts); break;
|
||||||
case Qet::East : d -> m_second_point = QPointF(-ts, 0.0); break;
|
case Qet::East : d -> second_point = QPointF(-ts, 0.0); break;
|
||||||
case Qet::South: d -> m_second_point = QPointF(0.0, -ts); break;
|
case Qet::South: d -> second_point = QPointF(0.0, -ts); break;
|
||||||
case Qet::West : d -> m_second_point = QPointF(ts, 0.0); break;
|
case Qet::West : d -> second_point = QPointF(ts, 0.0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,10 @@
|
|||||||
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
|
||||||
@@ -45,7 +42,6 @@ class PartTerminal : public CustomElementGraphicPart
|
|||||||
signals:
|
signals:
|
||||||
void orientationChanged();
|
void orientationChanged();
|
||||||
void nameChanged();
|
void nameChanged();
|
||||||
void terminalTypeChanged();
|
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
public:
|
public:
|
||||||
@@ -55,6 +51,7 @@ 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;
|
||||||
@@ -74,12 +71,7 @@ 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
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
@@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
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,8 +24,7 @@
|
|||||||
#include "../../qetinformation.h"
|
#include "../../qetinformation.h"
|
||||||
#include "../../ui/alignmenttextdialog.h"
|
#include "../../ui/alignmenttextdialog.h"
|
||||||
#include "../../ui/compositetexteditdialog.h"
|
#include "../../ui/compositetexteditdialog.h"
|
||||||
#include "../ui/qetelementeditor.h"
|
#include "../qetelementeditor.h"
|
||||||
#include "../elementscene.h"
|
|
||||||
#include "ui_dynamictextfieldeditor.h"
|
#include "ui_dynamictextfieldeditor.h"
|
||||||
|
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
@@ -225,9 +224,9 @@ void DynamicTextFieldEditor::fillInfoComboBox()
|
|||||||
ui -> m_elmt_info_cb -> clear();
|
ui -> m_elmt_info_cb -> clear();
|
||||||
|
|
||||||
QStringList strl;
|
QStringList strl;
|
||||||
auto type = elementEditor()->elementScene()->elementData().m_type;
|
QString type = elementEditor() -> elementScene() -> elementType();
|
||||||
|
|
||||||
if(type & ElementData::AllReport) {
|
if(type.contains("report")) {
|
||||||
strl = QETInformation::folioReportInfoKeys();
|
strl = QETInformation::folioReportInfoKeys();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -333,8 +332,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()->elementData().m_informations.value(m_parts[i] -> infoName()).toString());
|
elementEditor() -> elementScene() -> elementInformation().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,7 +20,6 @@
|
|||||||
#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>
|
||||||
|
|
||||||
@@ -38,7 +37,7 @@ class EditorDelegate : public QItemDelegate
|
|||||||
|
|
||||||
QWidget* createEditor(QWidget *parent,
|
QWidget* createEditor(QWidget *parent,
|
||||||
const QStyleOptionViewItem &option,
|
const QStyleOptionViewItem &option,
|
||||||
const QModelIndex &index) const override
|
const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if(index.column() == 1)
|
if(index.column() == 1)
|
||||||
{
|
{
|
||||||
@@ -51,14 +50,23 @@ class EditorDelegate : public QItemDelegate
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ElementPropertiesEditorWidget::ElementPropertiesEditorWidget
|
@brief ElementPropertiesEditorWidget::ElementPropertiesEditorWidget
|
||||||
* @param data
|
Default constructor
|
||||||
* @param parent
|
@param basic_type : QString of the drawed element
|
||||||
*/
|
@param kind_info : DiagramContext to store kindInfo of drawed element
|
||||||
ElementPropertiesEditorWidget::ElementPropertiesEditorWidget(ElementData data, QWidget *parent) :
|
@param elmt_info : the information of element (label, manufacturer etc...]
|
||||||
|
@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_data(data)
|
m_basic_type(basic_type),
|
||||||
|
m_kind_info (kind_info),
|
||||||
|
m_elmt_info (elmt_info)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setUpInterface();
|
setUpInterface();
|
||||||
@@ -82,29 +90,22 @@ 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(
|
||||||
m_data.m_type));
|
QVariant(m_basic_type)));
|
||||||
|
|
||||||
if (m_data.m_type == ElementData::Slave)
|
if (m_basic_type == "slave")
|
||||||
{
|
{
|
||||||
ui->m_state_cb->setCurrentIndex(
|
ui->m_state_cb->setCurrentIndex(
|
||||||
ui->m_state_cb->findData(
|
ui->m_state_cb->findData(
|
||||||
m_data.m_slave_state));
|
m_kind_info["state"].toString()));
|
||||||
ui->m_type_cb->setCurrentIndex (
|
ui->m_type_cb->setCurrentIndex (
|
||||||
ui->m_type_cb->findData(
|
ui->m_type_cb->findData(
|
||||||
m_data.m_slave_type));
|
m_kind_info["type"].toString()));
|
||||||
ui->m_number_ctc->setValue(m_data.m_contact_count);
|
ui->m_number_ctc->setValue(m_kind_info["number"].toInt());
|
||||||
}
|
}
|
||||||
else if (m_data.m_type == ElementData::Master) {
|
else if (m_basic_type == "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_data.m_master_type));
|
m_kind_info["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());
|
||||||
@@ -116,39 +117,33 @@ void ElementPropertiesEditorWidget::upDateInterface()
|
|||||||
void ElementPropertiesEditorWidget::setUpInterface()
|
void ElementPropertiesEditorWidget::setUpInterface()
|
||||||
{
|
{
|
||||||
// Type combo box
|
// Type combo box
|
||||||
ui->m_base_type_cb->addItem (tr("Simple"), ElementData::Simple);
|
ui->m_base_type_cb->addItem (tr("Simple"), QVariant("simple"));
|
||||||
ui->m_base_type_cb->addItem (tr("Maître"), ElementData::Master);
|
ui->m_base_type_cb->addItem (tr("Maître"), QVariant("master"));
|
||||||
ui->m_base_type_cb->addItem (tr("Esclave"), ElementData::Slave);
|
ui->m_base_type_cb->addItem (tr("Esclave"), QVariant("slave"));
|
||||||
ui->m_base_type_cb->addItem (tr("Renvoi de folio suivant"), ElementData::NextReport);
|
ui->m_base_type_cb->addItem (tr("Renvoi de folio suivant"),
|
||||||
ui->m_base_type_cb->addItem (tr("Renvoi de folio précédent"), ElementData::PreviousReport);
|
QVariant("next_report"));
|
||||||
ui->m_base_type_cb->addItem (tr("Bornier"), ElementData::Terminale);
|
ui->m_base_type_cb->addItem (tr("Renvoi de folio précédent"),
|
||||||
|
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"), ElementData::NO);
|
ui->m_state_cb->addItem(tr("Normalement ouvert"),QVariant("NO"));
|
||||||
ui->m_state_cb->addItem(tr("Normalement fermé"), ElementData::NC);
|
ui->m_state_cb->addItem(tr("Normalement fermé"), QVariant("NC"));
|
||||||
ui->m_state_cb->addItem(tr("Inverseur"), ElementData::SW);
|
ui->m_state_cb->addItem(tr("Inverseur"), QVariant("SW"));
|
||||||
ui->m_type_cb->addItem(tr("Simple"), ElementData::SSimple);
|
ui->m_type_cb->addItem(tr("Simple"), QVariant("simple"));
|
||||||
ui->m_type_cb->addItem(tr("Puissance"), ElementData::Power);
|
ui->m_type_cb->addItem(tr("Puissance"), QVariant("power"));
|
||||||
ui->m_type_cb->addItem(tr("Temporisé travail"), ElementData::DelayOn);
|
ui->m_type_cb->addItem(tr("Temporisé travail"), QVariant("delayOn"));
|
||||||
ui->m_type_cb->addItem(tr("Temporisé repos"), ElementData::DelayOff);
|
ui->m_type_cb->addItem(tr("Temporisé repos"), QVariant("delayOff"));
|
||||||
ui->m_type_cb->addItem(tr("Temporisé travail & repos"), ElementData::delayOnOff);
|
ui->m_type_cb->addItem(tr("Temporisé travail & repos"),
|
||||||
|
QVariant("delayOnOff"));
|
||||||
|
|
||||||
//Master option
|
//Master option
|
||||||
ui->m_master_type_cb->addItem(tr("Bobine"), ElementData::Coil);
|
ui->m_master_type_cb->addItem(tr("Bobine"), QVariant("coil"));
|
||||||
ui->m_master_type_cb->addItem(tr("Organe de protection"), ElementData::Protection);
|
ui->m_master_type_cb->addItem(tr("Organe de protection"),
|
||||||
ui->m_master_type_cb->addItem(tr("Commutateur / bouton"), ElementData::Commutator);
|
QVariant("protection"));
|
||||||
|
ui->m_master_type_cb->addItem(tr("Commutateur / bouton"),
|
||||||
//Terminal option
|
QVariant("commutator"));
|
||||||
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));
|
||||||
@@ -158,28 +153,21 @@ void ElementPropertiesEditorWidget::setUpInterface()
|
|||||||
|
|
||||||
void ElementPropertiesEditorWidget::updateTree()
|
void ElementPropertiesEditorWidget::updateTree()
|
||||||
{
|
{
|
||||||
auto type_ = ui->m_base_type_cb->currentData().value<ElementData::Type>();
|
QString type = ui->m_base_type_cb->itemData(
|
||||||
|
ui->m_base_type_cb->currentIndex()).toString();
|
||||||
switch (type_) {
|
|
||||||
case ElementData::Simple:
|
if (type == "master")
|
||||||
ui->m_tree->setEnabled(true);
|
ui->m_tree->setEnabled(true);
|
||||||
break;
|
else if (type == "slave")
|
||||||
case ElementData::NextReport:
|
ui->m_tree->setDisabled(true);
|
||||||
ui->m_tree->setDisabled(true);
|
else if (type == "simple")
|
||||||
break;
|
ui->m_tree->setEnabled(true);
|
||||||
case ElementData::PreviousReport:
|
else if (type == "next_report")
|
||||||
ui->m_tree->setDisabled(true);
|
ui->m_tree->setDisabled(true);
|
||||||
break;
|
else if (type == "previous_report")
|
||||||
case ElementData::Master:
|
ui->m_tree->setDisabled(true);
|
||||||
ui->m_tree->setEnabled(true);
|
else if (type == "terminal")
|
||||||
break;
|
ui->m_tree->setEnabled(true);
|
||||||
case ElementData::Slave:
|
|
||||||
ui->m_tree->setDisabled(true);
|
|
||||||
break;
|
|
||||||
case ElementData::Terminale:
|
|
||||||
ui->m_tree->setEnabled(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -187,16 +175,20 @@ 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()
|
||||||
{
|
{
|
||||||
const auto keys = QETInformation::elementEditorElementInfoKeys();
|
QStringList keys{"label", "plant", "comment", "description",
|
||||||
|
"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_data.m_informations.value(key).toString());
|
qtwi->setText(1, m_elmt_info.value(key).toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,21 +198,23 @@ void ElementPropertiesEditorWidget::populateTree()
|
|||||||
*/
|
*/
|
||||||
void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
||||||
{
|
{
|
||||||
m_data.m_type = ui->m_base_type_cb->currentData().value<ElementData::Type>();
|
m_basic_type = ui->m_base_type_cb->itemData(
|
||||||
|
ui->m_base_type_cb->currentIndex()).toString();
|
||||||
if (m_data.m_type == ElementData::Slave)
|
if (m_basic_type == "slave")
|
||||||
{
|
{
|
||||||
m_data.m_slave_state = ui->m_state_cb->currentData().value<ElementData::SlaveState>();
|
m_kind_info.addValue("state",
|
||||||
m_data.m_slave_type = ui->m_type_cb->currentData().value<ElementData::SlaveType>();
|
ui->m_state_cb->itemData(
|
||||||
m_data.m_contact_count = ui->m_number_ctc->value();
|
ui->m_state_cb->currentIndex()));
|
||||||
|
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_data.m_type == ElementData::Master) {
|
else if(m_basic_type == "master") {
|
||||||
m_data.m_master_type = ui->m_master_type_cb->currentData().value<ElementData::MasterType>();
|
m_kind_info.addValue("type",
|
||||||
}
|
ui->m_master_type_cb->itemData(
|
||||||
else if (m_data.m_type == ElementData::Terminale)
|
ui->m_master_type_cb->currentIndex()));
|
||||||
{
|
|
||||||
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())
|
||||||
@@ -230,8 +224,8 @@ void ElementPropertiesEditorWidget::on_m_buttonBox_accepted()
|
|||||||
txt.remove("\r");
|
txt.remove("\r");
|
||||||
txt.remove("\n");
|
txt.remove("\n");
|
||||||
|
|
||||||
m_data.m_informations.addValue(qtwi->data(0, Qt::UserRole).toString(),
|
m_elmt_info.addValue(qtwi->data(0, Qt::UserRole).toString(),
|
||||||
txt);
|
txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->close();
|
this->close();
|
||||||
@@ -241,23 +235,18 @@ 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(int index)
|
void ElementPropertiesEditorWidget::on_m_base_type_cb_currentIndexChanged(
|
||||||
|
int index)
|
||||||
{
|
{
|
||||||
bool slave = false , master = false, terminal = false;
|
bool slave = false , master = false;
|
||||||
|
|
||||||
auto type_ = ui->m_base_type_cb->itemData(index).value<ElementData::Type>();
|
if (ui->m_base_type_cb->itemData(index).toString() == "slave")
|
||||||
if (type_ == ElementData::Slave)
|
|
||||||
slave = true;
|
slave = true;
|
||||||
else if (type_ == ElementData::Master)
|
else if (ui->m_base_type_cb->itemData(index).toString() == "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,7 +19,6 @@
|
|||||||
#define ELEMENTPROPERTIESEDITORWIDGET_H
|
#define ELEMENTPROPERTIESEDITORWIDGET_H
|
||||||
|
|
||||||
#include "../../diagramcontext.h"
|
#include "../../diagramcontext.h"
|
||||||
#include "../../properties/elementdata.h"
|
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
@@ -39,13 +38,12 @@ class ElementPropertiesEditorWidget : public QDialog
|
|||||||
|
|
||||||
//METHODS
|
//METHODS
|
||||||
public:
|
public:
|
||||||
explicit ElementPropertiesEditorWidget(ElementData data, QWidget *parent = nullptr);
|
explicit ElementPropertiesEditorWidget(QString &basic_type, DiagramContext &kind_info, DiagramContext &elmt_info, QWidget *parent = nullptr);
|
||||||
~ElementPropertiesEditorWidget() override;
|
~ElementPropertiesEditorWidget() override;
|
||||||
|
|
||||||
ElementData editedData() {return m_data;}
|
void upDateInterface();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void upDateInterface();
|
|
||||||
void setUpInterface();
|
void setUpInterface();
|
||||||
void updateTree();
|
void updateTree();
|
||||||
void populateTree();
|
void populateTree();
|
||||||
@@ -58,7 +56,9 @@ class ElementPropertiesEditorWidget : public QDialog
|
|||||||
//ATTRIBUTES
|
//ATTRIBUTES
|
||||||
private:
|
private:
|
||||||
Ui::ElementPropertiesEditorWidget *ui;
|
Ui::ElementPropertiesEditorWidget *ui;
|
||||||
ElementData m_data;
|
QString &m_basic_type;
|
||||||
|
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>527</width>
|
<width>450</width>
|
||||||
<height>442</height>
|
<height>321</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -107,35 +107,6 @@
|
|||||||
</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
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user