Compare commits

..

6 Commits

Author SHA1 Message Date
Maximilian Federle
4f1567ec97 projectview: Only append .qet if not snap or flatpak 2022-01-26 17:04:17 +01:00
Maximilian Federle
e152717a05 add workflow for building candidate snap 2022-01-20 10:09:35 +01:00
Maximilian Federle
0f645e9b76 snap: set version manually 2022-01-20 09:53:17 +01:00
Maximilian Federle
821e681520 projectview: Re-enable appending qet suffix if not running as flatpak
It was removed in b121dad for all platforms.
Only disable appending the suffix for the flatpak platform
by testing for the FLATPAK_ID environment variable.
2022-01-20 09:46:19 +01:00
Maximilian Federle
d27bc35022 snap: Remove framework snap prompt
Now that https://github.com/snapcore/snapcraft/pull/3596 has been
released in snapcraft 6.0.1, drop the prompt that tells users to
disconnect the old framework snap.

Also drop --enable-experimental-extensions from CI  because kde-neon
has been declared stable for core20.
2022-01-20 09:45:43 +01:00
Maximilian Federle
61d3adad9b snap: Port to core20 2022-01-20 09:44:33 +01:00
79 changed files with 17010 additions and 17822 deletions

View File

@@ -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

View File

@@ -19,7 +19,7 @@ include(cmake/hoto_update_cmake_message.cmake)
cmake_minimum_required(VERSION 3.14...3.19 FATAL_ERROR)
project(qelectrotech
VERSION 0.9.0
VERSION 0.8.0
DESCRIPTION "QET is a CAD/CAE editor focusing on schematics drawing features."
HOMEPAGE_URL "https://qelectrotech.org/"
LANGUAGES CXX)
@@ -131,28 +131,3 @@ target_include_directories(
${QET_DIR}/sources/factory/ui
${QET_DIR}/sources/print
)
install(TARGETS ${PROJECT_NAME})
install(DIRECTORY ico/breeze-icons/16x16 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY ico/breeze-icons/22x22 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY ico/breeze-icons/32x32 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY ico/breeze-icons/48x48 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY ico/breeze-icons/64x64 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY ico/breeze-icons/128x128 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY ico/breeze-icons/256x256 DESTINATION ${QET_ICONS_PATH})
install(DIRECTORY elements DESTINATION share/qelectrotech)
install(DIRECTORY examples DESTINATION share/qelectrotech)
install(DIRECTORY titleblocks DESTINATION share/qelectrotech)
install(FILES LICENSE ELEMENTS.LICENSE CREDIT README ChangeLog DESTINATION share/doc/qelectrotech)
install(FILES misc/qelectrotech.desktop DESTINATION share/applications)
install(FILES misc/x-qet-element.xml
misc/x-qet-project.xml
misc/x-qet-titleblock.xml
DESTINATION share/mime/application)
install(FILES misc/x-qet-element.desktop
misc/x-qet-project.desktop
misc/x-qet-titleblock.desktop
DESTINATION share/mimelnk/application)
install(FILES misc/qelectrotech.xml DESTINATION share/mime/packages)
install(FILES misc/qelectrotech.appdata.xml DESTINATION ${QET_APPDATA_PATH})
install(FILES ${QM_FILES} DESTINATION ${QET_LANG_PATH})

View File

@@ -1,79 +1,12 @@
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__
----------
* Fallback to standard QApplication class on iOS and Android systems where
the library is not supported.
* Added Build CI tests to verify the library builds successfully on Linux, Windows and MacOS across multiple Qt versions.
_Anton Filimonov_

View File

@@ -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)
# 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
singleapplication.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
set(QT_COMPONENTS Core Network)
set(QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Core Qt${QT_DEFAULT_MAJOR_VERSION}::Network)
find_package(Qt5Network)
if(QAPPLICATION_CLASS STREQUAL QApplication)
list(APPEND QT_COMPONENTS Widgets)
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Widgets)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
elseif(QAPPLICATION_CLASS STREQUAL QGuiApplication)
list(APPEND QT_COMPONENTS Gui)
list(APPEND QT_LIBRARIES Qt${QT_DEFAULT_MAJOR_VERSION}::Gui)
find_package(Qt5 COMPONENTS Gui REQUIRED)
else()
set(QAPPLICATION_CLASS QCoreApplication)
find_package(Qt5 COMPONENTS Core REQUIRED)
endif()
add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
find_package(Qt${QT_DEFAULT_MAJOR_VERSION} COMPONENTS ${QT_COMPONENTS} REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC ${QT_LIBRARIES})
# Link dependencies
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Network)
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)
target_link_libraries(${PROJECT_NAME} PRIVATE advapi32)
endif()
target_compile_definitions(${PROJECT_NAME} PUBLIC QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@@ -1,6 +1,6 @@
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
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,8 +1,7 @@
SingleApplication
=================
[![CI](https://github.com/itay-grudev/SingleApplication/workflows/CI:%20Build%20Test/badge.svg)](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
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`
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
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
submodule to your project. Here is how:
submodule to your project and include it's contents with a `.pri` file. Here is
how:
```bash
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
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for 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
is not `QCoreApplication` as in examples above.
The `Instance Started` signal
-----------------------------
------------------------
The SingleApplication class implements a `instanceStarted()` signal. You can
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
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
---
### Members
```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
@@ -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
used to notify the primary instance whenever a secondary instance had been
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
recognizes.*
@@ -215,22 +204,6 @@ qint64 SingleApplication::primaryPid()
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
```cpp

View File

@@ -1 +0,0 @@
#include "singleapplication.h"

View File

@@ -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)

0
SingleApplication/examples/basic/basic.pro Executable file → Normal file
View File

2
SingleApplication/examples/basic/main.cpp Executable file → Normal file
View File

@@ -5,7 +5,5 @@ int main(int argc, char *argv[])
// Allow secondary instances
SingleApplication app( argc, argv );
qWarning() << "Started a new instance";
return app.exec();
}

View File

@@ -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)

View File

@@ -82,27 +82,27 @@ Calculator::Calculator(QWidget *parent)
digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked()));
}
Button *pointButton = createButton(".", SLOT(pointClicked()));
Button *changeSignButton = createButton("\302\261", SLOT(changeSignClicked()));
Button *pointButton = createButton(tr("."), SLOT(pointClicked()));
Button *changeSignButton = createButton(tr("\302\261"), SLOT(changeSignClicked()));
Button *backspaceButton = createButton("Backspace", SLOT(backspaceClicked()));
Button *clearButton = createButton("Clear", SLOT(clear()));
Button *clearAllButton = createButton("Clear All", SLOT(clearAll()));
Button *backspaceButton = createButton(tr("Backspace"), SLOT(backspaceClicked()));
Button *clearButton = createButton(tr("Clear"), SLOT(clear()));
Button *clearAllButton = createButton(tr("Clear All"), SLOT(clearAll()));
Button *clearMemoryButton = createButton("MC", SLOT(clearMemory()));
Button *readMemoryButton = createButton("MR", SLOT(readMemory()));
Button *setMemoryButton = createButton("MS", SLOT(setMemory()));
Button *addToMemoryButton = createButton("M+", SLOT(addToMemory()));
Button *clearMemoryButton = createButton(tr("MC"), SLOT(clearMemory()));
Button *readMemoryButton = createButton(tr("MR"), SLOT(readMemory()));
Button *setMemoryButton = createButton(tr("MS"), SLOT(setMemory()));
Button *addToMemoryButton = createButton(tr("M+"), SLOT(addToMemory()));
Button *divisionButton = createButton("\303\267", SLOT(multiplicativeOperatorClicked()));
Button *timesButton = createButton("\303\227", SLOT(multiplicativeOperatorClicked()));
Button *minusButton = createButton("-", SLOT(additiveOperatorClicked()));
Button *plusButton = createButton("+", SLOT(additiveOperatorClicked()));
Button *divisionButton = createButton(tr("\303\267"), SLOT(multiplicativeOperatorClicked()));
Button *timesButton = createButton(tr("\303\227"), SLOT(multiplicativeOperatorClicked()));
Button *minusButton = createButton(tr("-"), SLOT(additiveOperatorClicked()));
Button *plusButton = createButton(tr("+"), SLOT(additiveOperatorClicked()));
Button *squareRootButton = createButton("Sqrt", SLOT(unaryOperatorClicked()));
Button *powerButton = createButton("x\302\262", SLOT(unaryOperatorClicked()));
Button *reciprocalButton = createButton("1/x", SLOT(unaryOperatorClicked()));
Button *equalButton = createButton("=", SLOT(equalClicked()));
Button *squareRootButton = createButton(tr("Sqrt"), SLOT(unaryOperatorClicked()));
Button *powerButton = createButton(tr("x\302\262"), SLOT(unaryOperatorClicked()));
Button *reciprocalButton = createButton(tr("1/x"), SLOT(unaryOperatorClicked()));
Button *equalButton = createButton(tr("="), SLOT(equalClicked()));
//! [4]
//! [5]
@@ -140,7 +140,7 @@ Calculator::Calculator(QWidget *parent)
mainLayout->addWidget(equalButton, 5, 5);
setLayout(mainLayout);
setWindowTitle("Calculator");
setWindowTitle(tr("Calculator"));
}
//! [6]
@@ -169,15 +169,15 @@ void Calculator::unaryOperatorClicked()
double operand = display->text().toDouble();
double result = 0.0;
if (clickedOperator == "Sqrt") {
if (clickedOperator == tr("Sqrt")) {
if (operand < 0.0) {
abortOperation();
return;
}
result = std::sqrt(operand);
} else if (clickedOperator == "x\302\262") {
} else if (clickedOperator == tr("x\302\262")) {
result = std::pow(operand, 2.0);
} else if (clickedOperator == "1/x") {
} else if (clickedOperator == tr("1/x")) {
if (operand == 0.0) {
abortOperation();
return;
@@ -287,7 +287,7 @@ void Calculator::pointClicked()
if (waitingForOperand)
display->setText("0");
if (!display->text().contains('.'))
display->setText(display->text() + ".");
display->setText(display->text() + tr("."));
waitingForOperand = false;
}
//! [22]
@@ -299,7 +299,7 @@ void Calculator::changeSignClicked()
double value = text.toDouble();
if (value > 0.0) {
text.prepend("-");
text.prepend(tr("-"));
} else if (value < 0.0) {
text.remove(0, 1);
}
@@ -383,20 +383,20 @@ Button *Calculator::createButton(const QString &text, const char *member)
void Calculator::abortOperation()
{
clearAll();
display->setText("####");
display->setText(tr("####"));
}
//! [36]
//! [38]
bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
{
if (pendingOperator == "+") {
if (pendingOperator == tr("+")) {
sumSoFar += rightOperand;
} else if (pendingOperator == "-") {
} else if (pendingOperator == tr("-")) {
sumSoFar -= rightOperand;
} else if (pendingOperator == "\303\227") {
} else if (pendingOperator == tr("\303\227")) {
factorSoFar *= rightOperand;
} else if (pendingOperator == "\303\267") {
} else if (pendingOperator == tr("\303\267")) {
if (rightOperand == 0.0)
return false;
factorSoFar /= rightOperand;

View File

@@ -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)

3
SingleApplication/examples/sending_arguments/main.cpp Executable file → Normal file
View File

@@ -11,9 +11,6 @@ int main(int argc, char *argv[])
// If this is a secondary instance
if( app.isSecondary() ) {
app.sendMessage( app.arguments().join(' ').toUtf8() );
qDebug() << "App already running.";
qDebug() << "Primary instance PID: " << app.primaryPid();
qDebug() << "Primary instance user: " << app.primaryUser();
return 0;
} else {
QObject::connect(

View File

View File

@@ -1,6 +1,6 @@
// 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
// 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
// THE SOFTWARE.
#include <QtCore/QElapsedTimer>
#include <QtCore/QTime>
#include <QtCore/QThread>
#include <QtCore/QDateTime>
#include <QtCore/QByteArray>
#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_p.h"
/**
* @brief Constructor. Checks and fires up LocalServer or closes the program
* if another instance already exists
* @param argc
* @param argv
* @param allowSecondary Whether to enable secondary instance support
* @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, const QString &userData )
: app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
@brief Constructor. Checks and fires up LocalServer or closes the program
if another instance already exists
@param argc
@param argv
@param {bool} allowSecondaryInstances
*/
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout )
: app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
{
Q_D( SingleApplication );
Q_D(SingleApplication);
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
// On Android and iOS since the library is not supported fallback to
// standard QApplication behaviour by simply returning at this point.
qWarning() << "SingleApplication is not supported on Android and iOS systems.";
return;
// On Android and iOS since the library is not supported fallback to
// standard QApplication behaviour by simply returning at this point.
qWarning() << "SingleApplication is not supported on Android and iOS systems.";
return;
#endif
// Store the current mode of the program
d->options = options;
// Store the current mode of the program
d->options = options;
// Add any unique user data
if ( ! userData.isEmpty() )
d->addAppData( userData );
// Generating an application ID used for identifying the shared memory
// block and QLocalServer
d->genBlockServerName();
// To mitigate QSharedMemory issues with large amount of processes
// attempting to attach at the same time
SingleApplicationPrivate::randomSleep();
// Generating an application ID used for identifying the shared memory
// block and QLocalServer
d->genBlockServerName();
#ifdef Q_OS_UNIX
// By explicitly attaching it and then deleting it we make sure that the
// memory is deleted even after the process has crashed on Unix.
d->memory = new QSharedMemory( d->blockServerName );
d->memory->attach();
delete d->memory;
// By explicitly attaching it and then deleting it we make sure that the
// memory is deleted even after the process has crashed on Unix.
d->memory = new QSharedMemory( d->blockServerName );
d->memory->attach();
delete d->memory;
#endif
// Guarantee thread safe behaviour with a shared memory block.
d->memory = new QSharedMemory( d->blockServerName );
// Guarantee thread safe behaviour with a shared memory block.
d->memory = new QSharedMemory( d->blockServerName );
// Create a shared memory block
if( d->memory->create( sizeof( InstancesInfo ) )){
// Initialize the shared memory block
if( ! d->memory->lock() ){
qCritical() << "SingleApplication: Unable to lock memory block after create.";
abortSafely();
}
d->initializeMemoryBlock();
} else {
if( d->memory->error() == QSharedMemory::AlreadyExists ){
// Attempt to attach to the memory segment
if( ! d->memory->attach() ){
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
abortSafely();
}
if( ! d->memory->lock() ){
qCritical() << "SingleApplication: Unable to lock memory block after attach.";
abortSafely();
}
} else {
qCritical() << "SingleApplication: Unable to create block.";
abortSafely();
}
}
// Create a shared memory block
if( d->memory->create( sizeof( InstancesInfo ) ) ) {
// Initialize the shared memory block
d->memory->lock();
d->initializeMemoryBlock();
d->memory->unlock();
} else {
// Attempt to attach to the memory segment
if( ! d->memory->attach() ) {
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
qCritical() << d->memory->errorString();
delete d;
::exit( EXIT_FAILURE );
}
}
auto *inst = static_cast<InstancesInfo*>( d->memory->data() );
QElapsedTimer time;
time.start();
InstancesInfo* inst = static_cast<InstancesInfo*>( d->memory->data() );
QElapsedTimer time;
time.start();
// Make sure the shared memory block is initialised and in consistent state
while( true ){
// If the shared memory block's checksum is valid continue
if( d->blockChecksum() == inst->checksum ) break;
// Make sure the shared memory block is initialised and in consistent state
while( true ) {
d->memory->lock();
// If more than 5s have elapsed, assume the primary instance crashed and
// assume it's position
if( time.elapsed() > 5000 ){
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
d->initializeMemoryBlock();
}
if( d->blockChecksum() == inst->checksum ) break;
// Otherwise wait for a random period and try again. The random sleep here
// limits the probability of a collision between two racing apps and
// allows the app to initialise faster
if( ! d->memory->unlock() ){
qDebug() << "SingleApplication: Unable to unlock memory for random wait.";
qDebug() << d->memory->errorString();
}
SingleApplicationPrivate::randomSleep();
if( ! d->memory->lock() ){
qCritical() << "SingleApplication: Unable to lock memory after random wait.";
abortSafely();
}
}
if( time.elapsed() > 5000 ) {
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
d->initializeMemoryBlock();
}
if( inst->primary == false ){
d->startPrimary();
if( ! d->memory->unlock() ){
qDebug() << "SingleApplication: Unable to unlock memory after primary start.";
qDebug() << d->memory->errorString();
}
return;
}
d->memory->unlock();
// Check if another instance can be started
if( allowSecondary ){
d->startSecondary();
if( d->options & Mode::SecondaryNotification ){
d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
}
if( ! d->memory->unlock() ){
qDebug() << "SingleApplication: Unable to unlock memory after secondary start.";
qDebug() << d->memory->errorString();
}
return;
}
// Random sleep here limits the probability of a collision between two racing apps
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) // ### Qt 6: remove
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() );
QThread::sleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 ) );
#else
#if TODO_LIST
#pragma message("@TODO remove code for QT 5.10 or later")
#endif
quint32 value = QRandomGenerator::global()->generate();
QThread::sleep(8 + static_cast<unsigned long>(value / RAND_MAX * 10));
#endif
}
if( ! d->memory->unlock() ){
qDebug() << "SingleApplication: Unable to unlock memory at end of execution.";
qDebug() << d->memory->errorString();
}
if( inst->primary == false) {
d->startPrimary();
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()
{
Q_D( SingleApplication );
delete d;
Q_D(SingleApplication);
delete d;
}
/**
* Checks if the current application instance is primary.
* @return Returns true if the instance is primary, false otherwise.
*/
bool SingleApplication::isPrimary() const
bool SingleApplication::isPrimary()
{
Q_D( const SingleApplication );
return d->server != nullptr;
Q_D(SingleApplication);
return d->server != nullptr;
}
/**
* Checks if the current application instance is secondary.
* @return Returns true if the instance is secondary, false otherwise.
*/
bool SingleApplication::isSecondary() const
bool SingleApplication::isSecondary()
{
Q_D( const SingleApplication );
return d->server == nullptr;
Q_D(SingleApplication);
return d->server == nullptr;
}
/**
* 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
quint32 SingleApplication::instanceId()
{
Q_D( const SingleApplication );
return d->instanceNumber;
Q_D(SingleApplication);
return d->instanceNumber;
}
/**
* 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
qint64 SingleApplication::primaryPid()
{
Q_D( const SingleApplication );
return d->primaryPid();
Q_D(SingleApplication);
return d->primaryPid();
}
/**
* Returns the username the primary instance is running as.
* @return Returns the username the primary instance is running as.
*/
QString SingleApplication::primaryUser() const
bool SingleApplication::sendMessage( QByteArray message, int timeout )
{
Q_D( const SingleApplication );
return d->primaryUser();
}
/**
* Returns the username the current instance is running as.
* @return Returns the username the current instance is running as.
*/
QString SingleApplication::currentUser() const
{
return SingleApplicationPrivate::getUsername();
}
/**
* 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();
Q_D(SingleApplication);
// Nobody to connect to
if( isPrimary() ) return false;
// Make sure the socket is connected
d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect );
d->socket->write( message );
bool dataWritten = d->socket->waitForBytesWritten( timeout );
d->socket->flush();
return dataWritten;
}

View File

@@ -25,6 +25,7 @@
#include <QtCore/QtGlobal>
#include <QtNetwork/QLocalSocket>
#include <QElapsedTimer>
#ifndef QAPPLICATION_CLASS
#define QAPPLICATION_CLASS QCoreApplication
@@ -35,118 +36,99 @@
class SingleApplicationPrivate;
/**
* @brief The SingleApplication class handles multiple instances of the same
* Application
* @see QCoreApplication
*/
@brief The SingleApplication class handles multiple instances of the same
Application
@see QCoreApplication
*/
class SingleApplication : public QAPPLICATION_CLASS
{
Q_OBJECT
using app_t = QAPPLICATION_CLASS;
public:
/**
* @brief Mode of operation of SingleApplication.
* Whether the block should be user-wide or system-wide and whether the
* primary instance should be notified when a secondary instance had been
* started.
* @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
* block will be user wide.
* @enum
*/
enum Mode {
User = 1 << 0,
System = 1 << 1,
SecondaryNotification = 1 << 2,
ExcludeAppVersion = 1 << 3,
ExcludeAppPath = 1 << 4
};
Q_DECLARE_FLAGS(Options, Mode)
/**
* @brief Intitializes a SingleApplication instance with argc command line
* arguments in argv
* @arg {int &} argc - Number of arguments in argv
* @arg {const char *[]} argv - Supplied command line arguments
* @arg {bool} allowSecondary - Whether to start the instance as secondary
* if there is already a primary instance.
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
* User wide or System wide.
* @arg {int} timeout - Timeout to wait in milliseconds.
* @note argc and argv may be changed as Qt removes arguments that it
* recognizes
* @note Mode::SecondaryNotification only works if set on both the primary
* instance and the secondary instance.
* @note The timeout is just a hint for the maximum time of blocking
* operations. It does not guarantee that the SingleApplication
* initialisation will be completed in given time, though is a good hint.
* Usually 4*timeout would be the worst case (fail) scenario.
* @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 = {} );
~SingleApplication() override;
/**
* @brief Returns if the instance is the primary instance
* @returns {bool}
*/
bool isPrimary() const;
/**
* @brief Returns if the instance is a secondary instance
* @returns {bool}
*/
bool isSecondary() const;
/**
* @brief Returns a unique identifier for the current instance
* @returns {qint32}
*/
quint32 instanceId() const;
/**
* @brief Returns the process ID (PID) of the primary instance
* @returns {qint64}
*/
qint64 primaryPid() const;
/**
* @brief Returns the username of the user running the primary instance
* @returns {QString}
*/
QString primaryUser() const;
/**
* @brief Returns the username of the current user
* @returns {QString}
*/
QString currentUser() const;
/**
* @brief Sends a message to the primary instance. Returns true on success.
* @param {int} timeout - Timeout for connecting
* @returns {bool}
* @note sendMessage() will return false if invoked from the primary
* instance.
*/
bool sendMessage( const QByteArray &message, int timeout = 100 );
/**
* @brief Get the set user data.
* @returns {QStringList}
*/
QStringList userData() const;
Q_SIGNALS:
void instanceStarted();
void receivedMessage( quint32 instanceId, QByteArray message );
private:
SingleApplicationPrivate *d_ptr;
Q_DECLARE_PRIVATE(SingleApplication)
void abortSafely();
Q_OBJECT
typedef QAPPLICATION_CLASS app_t;
public:
/**
@brief Mode of operation of SingleApplication.
Whether the block should be user-wide or system-wide and whether the
primary instance should be notified when a secondary instance had been
started.
@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
block will be user wide.
@enum
*/
enum Mode {
User = 1 << 0,
System = 1 << 1,
SecondaryNotification = 1 << 2,
ExcludeAppVersion = 1 << 3,
ExcludeAppPath = 1 << 4
};
Q_DECLARE_FLAGS(Options, Mode)
/**
@brief Intitializes a SingleApplication instance with argc command line
arguments in argv
@arg {int &} argc - Number of arguments in argv
@arg {const char *[]} argv - Supplied command line arguments
@arg {bool} allowSecondary - Whether to start the instance as secondary
if there is already a primary instance.
@arg {Mode} mode - Whether for the SingleApplication block to be applied
User wide or System wide.
@arg {int} timeout - Timeout to wait in milliseconds.
@note argc and argv may be changed as Qt removes arguments that it
recognizes
@note Mode::SecondaryNotification only works if set on both the primary
instance and the secondary instance.
@note The timeout is just a hint for the maximum time of blocking
operations. It does not guarantee that the SingleApplication
initialisation will be completed in given time, though is a good hint.
Usually 4*timeout would be the worst case (fail) scenario.
@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 );
~SingleApplication();
/**
@brief Returns if the instance is the primary instance
@returns {bool}
*/
bool isPrimary();
/**
@brief Returns if the instance is a secondary instance
@returns {bool}
*/
bool isSecondary();
/**
@brief Returns a unique identifier for the current instance
@returns {qint32}
*/
quint32 instanceId();
/**
@brief Returns the process ID (PID) of the primary instance
@returns {qint64}
*/
qint64 primaryPid();
/**
@brief Sends a message to the primary instance. Returns true on success.
@param {int} timeout - Timeout for connecting
@returns {bool}
@note sendMessage() will return false if invoked from the primary
instance.
*/
bool sendMessage( QByteArray message, int timeout = 100 );
Q_SIGNALS:
void instanceStarted();
void receivedMessage( quint32 instanceId, QByteArray message );
private:
SingleApplicationPrivate *d_ptr;
Q_DECLARE_PRIVATE(SingleApplication)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)

View File

@@ -1,8 +1,7 @@
QT += core network
CONFIG += c++11
CONFIG += c++17
HEADERS += $$PWD/SingleApplication \
$$PWD/singleapplication.h \
HEADERS += $$PWD/singleapplication.h \
$$PWD/singleapplication_p.h
SOURCES += $$PWD/singleapplication.cpp \
$$PWD/singleapplication_p.cpp

View File

@@ -1,6 +1,6 @@
// 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
// of this software and associated documentation files (the "Software"), to deal
@@ -33,454 +33,412 @@
#include <cstddef>
#include <QtCore/QDir>
#include <QtCore/QThread>
#include <QtCore/QByteArray>
#include <QtCore/QDataStream>
#include <QtCore/QElapsedTimer>
#include <QtCore/QCryptographicHash>
#include <QtNetwork/QLocalServer>
#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_p.h"
#ifdef Q_OS_UNIX
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#endif
#ifdef Q_OS_WIN
#ifndef NOMINMAX
#define NOMINMAX 1
#endif
#include <windows.h>
#include <lmcons.h>
#include <windows.h>
#include <lmcons.h>
#endif
SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr )
: q_ptr( q_ptr )
: q_ptr( q_ptr )
{
server = nullptr;
socket = nullptr;
memory = nullptr;
instanceNumber = 0;
server = nullptr;
socket = nullptr;
memory = nullptr;
instanceNumber = -1;
}
SingleApplicationPrivate::~SingleApplicationPrivate()
{
if( socket != nullptr ){
socket->close();
delete socket;
}
if( socket != nullptr ) {
socket->close();
delete socket;
}
if( memory != nullptr ){
memory->lock();
auto *inst = static_cast<InstancesInfo*>(memory->data());
if( server != nullptr ){
server->close();
delete server;
inst->primary = false;
inst->primaryPid = -1;
inst->primaryUser[0] = '\0';
inst->checksum = blockChecksum();
}
memory->unlock();
memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
if( server != nullptr ) {
server->close();
delete server;
inst->primary = false;
inst->primaryPid = -1;
inst->checksum = blockChecksum();
}
memory->unlock();
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
delete memory;
}
void SingleApplicationPrivate::genBlockServerName()
{
QCryptographicHash appData( QCryptographicHash::Sha256 );
appData.addData( "SingleApplication", 17 );
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
QCryptographicHash appData( QCryptographicHash::Sha256 );
appData.addData( "SingleApplication", 17 );
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
if ( ! appDataList.isEmpty() )
appData.addData( appDataList.join( "" ).toUtf8() );
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ) {
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
}
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
}
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ) {
#ifdef Q_OS_WIN
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
#else
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
#endif
}
}
// User level block requires a user specific data in the hash
if( options & SingleApplication::Mode::User ){
appData.addData( getUsername().toUtf8() );
}
// User level block requires a user specific data in the hash
if( options & SingleApplication::Mode::User ) {
#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
// server naming requirements.
blockServerName = appData.result().toBase64().replace("/", "_");
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
// server naming requirements.
blockServerName = appData.result().toBase64().replace("/", "_");
}
void SingleApplicationPrivate::initializeMemoryBlock() const
void SingleApplicationPrivate::initializeMemoryBlock()
{
auto *inst = static_cast<InstancesInfo*>( memory->data() );
inst->primary = false;
inst->secondary = 0;
inst->primaryPid = -1;
inst->primaryUser[0] = '\0';
inst->checksum = blockChecksum();
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
inst->primary = false;
inst->secondary = 0;
inst->primaryPid = -1;
inst->checksum = blockChecksum();
}
void SingleApplicationPrivate::startPrimary()
{
// Reset the number of connections
auto *inst = static_cast <InstancesInfo*>( memory->data() );
Q_Q(SingleApplication);
inst->primary = true;
inst->primaryPid = QCoreApplication::applicationPid();
qstrncpy( inst->primaryUser, getUsername().toUtf8().data(), sizeof(inst->primaryUser) );
inst->checksum = blockChecksum();
instanceNumber = 0;
// Successful creation means that no main process exists
// So we start a QLocalServer to listen for connections
QLocalServer::removeServer( blockServerName );
server = new QLocalServer();
// 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
// SingleApplication::Mode::User flag on User level or no restrictions
if( options & SingleApplication::Mode::User ){
server->setSocketOptions( QLocalServer::UserAccessOption );
} else {
server->setSocketOptions( QLocalServer::WorldAccessOption );
}
// Restrict access to the socket according to the
// SingleApplication::Mode::User flag on User level or no restrictions
if( options & SingleApplication::Mode::User ) {
server->setSocketOptions( QLocalServer::UserAccessOption );
} else {
server->setSocketOptions( QLocalServer::WorldAccessOption );
}
server->listen( blockServerName );
QObject::connect(
server,
&QLocalServer::newConnection,
this,
&SingleApplicationPrivate::slotConnectionEstablished
);
server->listen( blockServerName );
QObject::connect(
server,
&QLocalServer::newConnection,
this,
&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()
{
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;
time.start();
// Connect to the Local Server of the Primary Instance if not already
// connected.
if( socket == nullptr ) {
socket = new QLocalSocket();
}
// Connect to the Local Server of the Primary Instance if not already
// connected.
if( socket == nullptr ){
socket = new QLocalSocket();
}
// If already connected - we are done;
if( socket->state() == QLocalSocket::ConnectedState )
return;
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 ){
randomSleep();
if( socket->state() != QLocalSocket::ConnectingState )
socket->connectToServer( blockServerName );
if( socket->state() == QLocalSocket::ConnectingState ){
socket->waitForConnected( static_cast<int>(msecs - time.elapsed()) );
}
// If connected break out of the loop
if( socket->state() == QLocalSocket::ConnectedState ) break;
// If elapsed time since start is longer than the method timeout return
if( time.elapsed() >= msecs ) return false;
}
}
// Initialisation message according to the SingleApplication protocol
QByteArray initMsg;
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
// Initialisation message according to the SingleApplication protocol
if( socket->state() == QLocalSocket::ConnectedState ) {
// Notify the parent that a new instance had been started;
QByteArray initMsg;
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
writeStream.setVersion(QDataStream::Qt_5_6);
writeStream.setVersion(QDataStream::Qt_5_6);
#endif
writeStream << blockServerName.toLatin1();
writeStream << static_cast<quint8>(connectionType);
writeStream << instanceNumber;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
quint16 checksum = qChecksum(QByteArray(initMsg, static_cast<quint32>(initMsg.length())));
writeStream << blockServerName.toLatin1();
writeStream << static_cast<quint8>(connectionType);
writeStream << instanceNumber;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
quint16 checksum =
qChecksum(
initMsg.constData(),
static_cast<quint32>(initMsg.length()));
#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
writeStream << checksum;
quint16 checksum =
qChecksum(
QByteArrayView(
initMsg.constData(),
static_cast<quint32>(initMsg.length())));
#endif
writeStream << checksum;
// The header indicates the message length that follows
QByteArray header;
QDataStream headerStream(&header, QIODevice::WriteOnly);
// The header indicates the message length that follows
QByteArray header;
QDataStream headerStream(&header, QIODevice::WriteOnly);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
headerStream.setVersion(QDataStream::Qt_5_6);
headerStream.setVersion(QDataStream::Qt_5_6);
#endif
headerStream << static_cast <quint64>( initMsg.length() );
headerStream << static_cast <quint64>( initMsg.length() );
socket->write( header );
socket->write( initMsg );
bool result = socket->waitForBytesWritten( static_cast<int>(msecs - time.elapsed()) );
socket->flush();
return result;
socket->write( header );
socket->write( initMsg );
socket->flush();
socket->waitForBytesWritten( msecs );
}
}
quint16 SingleApplicationPrivate::blockChecksum() const
quint16 SingleApplicationPrivate::blockChecksum()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
quint16 checksum = qChecksum(QByteArray(static_cast<const char*>(memory->constData()), offsetof(InstancesInfo, checksum)));
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
return qChecksum(
static_cast <const char *>( memory->data() ),
offsetof( InstancesInfo, checksum )
);
#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
return checksum;
}
qint64 SingleApplicationPrivate::primaryPid() const
qint64 SingleApplicationPrivate::primaryPid()
{
qint64 pid;
qint64 pid;
memory->lock();
auto *inst = static_cast<InstancesInfo*>( memory->data() );
pid = inst->primaryPid;
memory->unlock();
memory->lock();
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
pid = inst->primaryPid;
memory->unlock();
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 );
return pid;
}
/**
* @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()
{
QLocalSocket *nextConnSocket = server->nextPendingConnection();
connectionMap.insert(nextConnSocket, ConnectionInfo());
QLocalSocket *nextConnSocket = server->nextPendingConnection();
connectionMap.insert(nextConnSocket, ConnectionInfo());
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
[nextConnSocket, this](){
auto &info = connectionMap[nextConnSocket];
Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
}
);
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
[nextConnSocket, this]() {
auto &info = connectionMap[nextConnSocket];
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,
[nextConnSocket, this](){
connectionMap.remove(nextConnSocket);
}
);
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
[nextConnSocket, this](){
auto &info = connectionMap[nextConnSocket];
switch(info.stage){
case StageHeader:
readInitMessageHeader(nextConnSocket);
break;
case StageBody:
readInitMessageBody(nextConnSocket);
break;
case StageConnected:
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
break;
default:
break;
};
}
);
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
[nextConnSocket, this]() {
auto &info = connectionMap[nextConnSocket];
switch(info.stage) {
case StageHeader:
readInitMessageHeader(nextConnSocket);
break;
case StageBody:
readInitMessageBody(nextConnSocket);
break;
case StageConnected:
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
break;
default:
break;
};
}
);
}
void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
{
if (!connectionMap.contains( sock )){
return;
}
if (!connectionMap.contains( sock )) {
return;
}
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ){
return;
}
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ) {
return;
}
QDataStream headerStream( sock );
QDataStream headerStream( sock );
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
headerStream.setVersion( QDataStream::Qt_5_6 );
headerStream.setVersion( QDataStream::Qt_5_6 );
#endif
// Read the header to know the message length
quint64 msgLen = 0;
headerStream >> msgLen;
ConnectionInfo &info = connectionMap[sock];
info.stage = StageBody;
info.msgLen = msgLen;
// Read the header to know the message length
quint64 msgLen = 0;
headerStream >> msgLen;
ConnectionInfo &info = connectionMap[sock];
info.stage = StageBody;
info.msgLen = msgLen;
if ( sock->bytesAvailable() >= (qint64) msgLen ){
readInitMessageBody( sock );
}
if ( sock->bytesAvailable() >= (qint64) msgLen ) {
readInitMessageBody( sock );
}
}
void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
{
Q_Q(SingleApplication);
Q_Q(SingleApplication);
if (!connectionMap.contains( sock )){
return;
}
if (!connectionMap.contains( sock )) {
return;
}
ConnectionInfo &info = connectionMap[sock];
if( sock->bytesAvailable() < ( qint64 )info.msgLen ){
return;
}
ConnectionInfo &info = connectionMap[sock];
if( sock->bytesAvailable() < ( qint64 )info.msgLen ) {
return;
}
// Read the message body
QByteArray msgBytes = sock->read(info.msgLen);
QDataStream readStream(msgBytes);
// Read the message body
QByteArray msgBytes = sock->read(info.msgLen);
QDataStream readStream(msgBytes);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
readStream.setVersion( QDataStream::Qt_5_6 );
readStream.setVersion( QDataStream::Qt_5_6 );
#endif
// server name
QByteArray latin1Name;
readStream >> latin1Name;
// server name
QByteArray latin1Name;
readStream >> latin1Name;
// connection type
ConnectionType connectionType = InvalidConnection;
quint8 connTypeVal = InvalidConnection;
readStream >> connTypeVal;
connectionType = static_cast <ConnectionType>( connTypeVal );
// connection type
ConnectionType connectionType = InvalidConnection;
quint8 connTypeVal = InvalidConnection;
readStream >> connTypeVal;
connectionType = static_cast <ConnectionType>( connTypeVal );
// instance id
quint32 instanceId = 0;
readStream >> instanceId;
// instance id
quint32 instanceId = 0;
readStream >> instanceId;
// checksum
quint16 msgChecksum = 0;
readStream >> msgChecksum;
// checksum
quint16 msgChecksum = 0;
readStream >> msgChecksum;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
const quint16 actualChecksum = qChecksum(QByteArray(msgBytes, static_cast<quint32>(msgBytes.length() - sizeof(quint16))));
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
const quint16 actualChecksum =
qChecksum(
msgBytes.constData(),
static_cast<quint32>( msgBytes.length() - sizeof( quint16 ) ) );
#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
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 &&
QLatin1String(latin1Name) == blockServerName &&
msgChecksum == actualChecksum;
if( !isValid ) {
sock->close();
return;
}
if( !isValid ){
sock->close();
return;
}
info.instanceId = instanceId;
info.stage = StageConnected;
info.instanceId = instanceId;
info.stage = StageConnected;
if( connectionType == NewInstance ||
( connectionType == SecondaryInstance &&
options & SingleApplication::Mode::SecondaryNotification ) )
{
Q_EMIT q->instanceStarted();
}
if( connectionType == NewInstance ||
( connectionType == SecondaryInstance &&
options & SingleApplication::Mode::SecondaryNotification ) )
{
Q_EMIT q->instanceStarted();
}
if (sock->bytesAvailable() > 0){
Q_EMIT this->slotDataAvailable( sock, instanceId );
}
if (sock->bytesAvailable() > 0) {
Q_EMIT this->slotDataAvailable( sock, instanceId );
}
}
void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
{
Q_Q(SingleApplication);
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
Q_Q(SingleApplication);
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
}
void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
{
if( closedSocket->bytesAvailable() > 0 )
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;
if( closedSocket->bytesAvailable() > 0 )
Q_EMIT slotDataAvailable( closedSocket, instanceId );
}

View File

@@ -1,6 +1,6 @@
// 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
// of this software and associated documentation files (the "Software"), to deal
@@ -38,67 +38,62 @@
#include "singleapplication.h"
struct InstancesInfo {
bool primary;
quint32 secondary;
qint64 primaryPid;
char primaryUser[128];
quint16 checksum; // Must be the last field
bool primary;
quint32 secondary;
qint64 primaryPid;
quint16 checksum;
};
struct ConnectionInfo {
qint64 msgLen = 0;
quint32 instanceId = 0;
quint8 stage = 0;
explicit ConnectionInfo() :
msgLen(0), instanceId(0), stage(0) {}
qint64 msgLen;
quint32 instanceId;
quint8 stage;
};
class SingleApplicationPrivate : public QObject {
Q_OBJECT
public:
enum ConnectionType : quint8 {
InvalidConnection = 0,
NewInstance = 1,
SecondaryInstance = 2,
Reconnect = 3
};
enum ConnectionStage : quint8 {
StageHeader = 0,
StageBody = 1,
StageConnected = 2,
};
Q_DECLARE_PUBLIC(SingleApplication)
SingleApplicationPrivate( SingleApplication *q_ptr );
~SingleApplicationPrivate() override;
static QString getUsername();
void genBlockServerName();
void initializeMemoryBlock() const;
void startPrimary();
void startSecondary();
bool connectToPrimary( int msecs, ConnectionType connectionType );
quint16 blockChecksum() const;
qint64 primaryPid() const;
QString primaryUser() const;
void readInitMessageHeader(QLocalSocket *socket);
void readInitMessageBody(QLocalSocket *socket);
static void randomSleep();
void addAppData(const QString &data);
QStringList appData() const;
SingleApplication *q_ptr;
QSharedMemory *memory;
QLocalSocket *socket;
QLocalServer *server;
quint32 instanceNumber;
QString blockServerName;
SingleApplication::Options options;
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
QStringList appDataList;
public Q_SLOTS:
void slotConnectionEstablished();
void slotDataAvailable( QLocalSocket*, quint32 );
void slotClientConnectionClosed( QLocalSocket*, quint32 );
Q_OBJECT
public:
enum ConnectionType : quint8 {
InvalidConnection = 0,
NewInstance = 1,
SecondaryInstance = 2,
Reconnect = 3
};
enum ConnectionStage : quint8 {
StageHeader = 0,
StageBody = 1,
StageConnected = 2,
};
Q_DECLARE_PUBLIC(SingleApplication)
SingleApplicationPrivate( SingleApplication *q_ptr );
~SingleApplicationPrivate();
void genBlockServerName();
void initializeMemoryBlock();
void startPrimary();
void startSecondary();
void connectToPrimary(int msecs, ConnectionType connectionType );
quint16 blockChecksum();
qint64 primaryPid();
void readInitMessageHeader(QLocalSocket *socket);
void readInitMessageBody(QLocalSocket *socket);
SingleApplication *q_ptr;
QSharedMemory *memory;
QLocalSocket *socket;
QLocalServer *server;
quint32 instanceNumber;
QString blockServerName;
SingleApplication::Options options;
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
public Q_SLOTS:
void slotConnectionEstablished();
void slotDataAvailable( QLocalSocket*, quint32 );
void slotClientConnectionClosed( QLocalSocket*, quint32 );
};
#endif // SINGLEAPPLICATION_P_H

View File

@@ -1,15 +1,5 @@
#!/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
from="$SNAP_USER_DATA/.qet"
to="$SNAP_USER_COMMON/.qet"
@@ -23,12 +13,4 @@ fi
mkdir -p "$HOME/.qet"
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 "${@}"

View File

@@ -1,7 +1,7 @@
name: qelectrotech
title: QElectroTech
base: core18
adopt-info: qelectrotech
base: core20
version: "0.8.0"
license: GPL-2.0
summary: Electrical diagram editor
description: |
@@ -10,10 +10,7 @@ description: |
grade: stable
confinement: strict
architectures:
- build-on: amd64
run-on: amd64
compression: lzo
layout:
/usr/local/share/qelectrotech:
@@ -30,15 +27,14 @@ apps:
extensions: [kde-neon]
plugs: &plugs [opengl, unity7, home, removable-media, gsettings, network, cups-control]
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
QT_QPA_PLATFORMTHEME: gtk3
QT_AUTO_SCREEN_SCALE_FACTOR: 1
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:
command: bin/qelectrotech-launch $SNAP/bin/qet_tb_generator
command: bin/qet_tb_generator
command-chain:
- bin/qelectrotech-launch
extensions: [kde-neon]
plugs: *plugs
environment: *env
@@ -58,8 +54,8 @@ parts:
qet-tb-generator:
plugin: python
python-version: python3
source: https://github.com/qelectrotech/qet_tb_generator.git
source: https://github.com/raulroda/qet_tb_generator-plugin.git
python-packages: [PySimpleGUI]
stage-packages:
- python3-lxml
- python3-tk
@@ -68,15 +64,15 @@ parts:
kde-sdk-setup:
plugin: nil
build-snaps:
- kde-frameworks-5-core18-sdk
- kde-frameworks-5-qt-5-15-3-core20-sdk
build-packages:
- g++
- mesa-common-dev
- libglvnd-dev
- rsync
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:
after: [kde-sdk-setup]
plugin: nil
@@ -91,19 +87,15 @@ parts:
after: [kde-sdk-setup]
plugin: nil
source: .
stage-packages: [ git, sqlite3 ]
stage-packages: [ git, sqlite3, xdg-user-dirs ]
build-packages:
- git
- 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: |
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"
make -j$(nproc)
make -j${SNAPCRAFT_PARALLEL_BUILD_COUNT}
make install INSTALL_ROOT="$SNAPCRAFT_PART_INSTALL"
override-stage: |
snapcraftctl stage
@@ -114,11 +106,14 @@ parts:
cleanup:
after: [qelectrotech, dxf-to-qet, qet-tb-generator]
plugin: nil
build-snaps: [core18, kde-frameworks-5-core18]
build-snaps: [kde-frameworks-5-qt-5-15-3-core20]
override-prime: |
# Remove all files from snap that are already included in the base snap or in
# any connected content snaps
set -eux
for snap in "core18" "kde-frameworks-5-core18"; do # List all content-snaps and base snaps you're using here
cd "/snap/$snap/current" && find . -type f,l -exec rm -f "$SNAPCRAFT_PRIME/{}" \;
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/{}" "$SNAPCRAFT_PRIME/usr/{}" \;
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

View File

@@ -19,9 +19,9 @@ message(" - fetch_kdeaddons")
if(DEFINED BUILD_WITH_KF5)
Include(FetchContent)
option(BUILD_KF5 "Build KF5 libraries, use system ones otherwise" YES)
set(BUILD_KF5_YES "YES")
if(BUILD_KF5)
if(DEFINED BUILD_KF5_YES)
if(NOT DEFINED KF5_GIT_TAG)
#https://qelectrotech.org/forum/viewtopic.php?pid=13924#p13924

View File

@@ -18,16 +18,9 @@ message(" - fetch_pugixml")
Include(FetchContent)
option(BUILD_PUGIXML "Build pugixml library, use system one otherwise" YES)
FetchContent_Declare(
pugixml
GIT_REPOSITORY https://github.com/zeux/pugixml.git
GIT_TAG v1.11.1)
if(BUILD_PUGIXML)
FetchContent_Declare(
pugixml
GIT_REPOSITORY https://github.com/zeux/pugixml.git
GIT_TAG v1.11.4)
FetchContent_MakeAvailable(pugixml)
else()
find_package(pugixml REQUIRED)
endif()
FetchContent_MakeAvailable(pugixml)

View File

@@ -26,6 +26,6 @@ Include(FetchContent)
FetchContent_Declare(
SingleApplication
GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication.git
GIT_TAG v3.2.0)
GIT_TAG v3.1.5)
FetchContent_MakeAvailable(SingleApplication)

View File

@@ -28,6 +28,9 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
# This strips terminating newline in the variable
string(REGEX REPLACE "\n$" "" GIT_COMMIT_SHA "${GIT_COMMIT_SHA}")
# This adds to definitions => .cpp
add_definitions(-DGIT_COMMIT_SHA="${GIT_COMMIT_SHA}")
if(NOT GIT_COMMIT_RESULT EQUAL "0")
message(
FATAL_ERROR
@@ -36,6 +39,3 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
", please check")
endif()
endif()
# This adds to definitions => .cpp
add_definitions(-DGIT_COMMIT_SHA="${GIT_COMMIT_SHA}")

View File

@@ -52,8 +52,6 @@ set(QET_RES_FILES
${QET_DIR}/sources/editor/ui/lineeditor.ui
${QET_DIR}/sources/editor/ui/polygoneditor.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/factory/ui/addtabledialog.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/elementview.cpp
${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.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.h
@@ -318,12 +320,8 @@ set(QET_SRC_FILES
${QET_DIR}/sources/editor/ui/polygoneditor.h
${QET_DIR}/sources/editor/ui/rectangleeditor.cpp
${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.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.h
@@ -373,8 +371,6 @@ set(QET_SRC_FILES
${QET_DIR}/sources/print/projectprintwindow.cpp
${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.h
${QET_DIR}/sources/properties/reportproperties.cpp
@@ -383,8 +379,6 @@ set(QET_SRC_FILES
${QET_DIR}/sources/properties/terminaldata.h
${QET_DIR}/sources/properties/xrefproperties.cpp
${QET_DIR}/sources/properties/xrefproperties.h
${QET_DIR}/sources/properties/userproperties.cpp
${QET_DIR}/sources/properties/userproperties.h
${QET_DIR}/sources/PropertiesEditor/propertieseditordialog.h
${QET_DIR}/sources/PropertiesEditor/propertieseditordockwidget.cpp

View File

@@ -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}"/>
<names>
<name lang="cs">Motorový spouštěč 1P+N</name>
@@ -12,9 +12,6 @@
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
<name lang="hu">Motorvédő kapcsoló 1 pólusú GV</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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}"/>
<names>
<name lang="fr">Disjoncteur Magnéto-thermique GV 2P</name>
@@ -8,9 +8,6 @@
<name lang="cs">Motorový spouštěč 2P</name>
<name lang="hu">Motorvédő kapcsoló 2 pólusú GV</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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}"/>
<names>
<name lang="de">Motorschutzschalter</name>
@@ -12,9 +12,6 @@
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
<name lang="hu">Motorvédő kapcsoló 3F + N pólusú</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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}"/>
<names>
<name lang="el">Θερμομαγνητικό</name>
@@ -12,9 +12,6 @@
<name lang="de">Motorschutzschalter</name>
<name lang="hu">Motorvédő kapcsoló 4 pólusú GV</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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>
<name lang="en">Motor circuit breaker</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="hu">Motorvédő kapcsoló 3 pólusú</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations>Author: The QElectroTech team
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
<description>

View File

@@ -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>
<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>
@@ -10,9 +10,6 @@
<name lang="pl">Wyłącznik silnikowy</name>
<name lang="hu">Motorvédő kapcsoló 3F + N pólusú</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations>Author: The QElectroTech team
License: see http://qelectrotech.org/wiki/doc/elements_license</informations>
<description>

View File

@@ -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}"/>
<names>
<name lang="fr">Disjoncteur differentiel 1P+N</name>
@@ -8,9 +8,6 @@
<name lang="cs">Jističochránič 2P</name>
<name lang="hu">Differenciál-védőkapcsoló 1P+N termikus és zárlatvédelemmel</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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}"/>
<names>
<name lang="cs">Jističochránič 3P+N</name>
@@ -12,9 +12,6 @@
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
<name lang="hu">Differenciál-védőkapcsoló 3P+N termikus és zárlatvédelemmel</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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}"/>
<names>
<name lang="fr">Disjoncteur differentiel 2P</name>
@@ -8,9 +8,6 @@
<name lang="cs">Jističochránič 2P</name>
<name lang="hu">Differenciál-védőkapcsoló 2P termikus és zárlatvédelemmel</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

View File

@@ -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}"/>
<names>
<name lang="cs">Jističochránič 3P</name>
@@ -12,9 +12,6 @@
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
<name lang="hu">Differenciál-védőkapcsoló 3P termikus és zárlatvédelemmel</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<description>
<text text="I>" size="9" y="25" x="-24"/>

View File

@@ -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}"/>
<names>
<name lang="de">Motorschutzschalter</name>
@@ -12,9 +12,6 @@
<name lang="ar">قاطع مغناطيسي-حراري GV</name>
<name lang="hu">Differenciál-védőkapcsoló 4P termikus és zárlatvédelemmel</name>
</names>
<kindInformations>
<kindInformation name="type" show="1">protection</kindInformation>
</kindInformations>
<informations></informations>
<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"/>

Binary file not shown.

View File

@@ -826,7 +826,7 @@ Uwaga: te opcje nie pozwalają na zablokowanie automatycznej numeracji tylko ust
<message>
<location filename="../sources/ui/conductorpropertieswidget.ui" line="58"/>
<source>Couleur du texte:</source>
<translation>Kolor tekstu:</translation>
<translation>Kolor tekstu</translation>
</message>
<message>
<location filename="../sources/ui/conductorpropertieswidget.ui" line="151"/>
@@ -2600,7 +2600,7 @@ Wszystkie elementy i podkatalogi znajdujące się w tym katalogu zostaną usuni
<message>
<location filename="../sources/editor/ui/ellipseeditor.ui" line="23"/>
<source>Centre :</source>
<translation>Środek:</translation>
<translation>Środek</translation>
</message>
<message>
<location filename="../sources/editor/ui/ellipseeditor.ui" line="30"/>
@@ -5005,7 +5005,7 @@ Poniższe zmienne są zgodne:
<message>
<location filename="../sources/print/projectprintwindow.ui" line="225"/>
<source>Si cette option est cochée, les marges de la feuille seront ignorées et toute sa surface sera utilisée pour l&apos;impression. Cela peut ne pas être supporté par votre imprimante.</source>
<translation>Jeżeli ta opcja jest zaznaczona, marginesy arkusza zostaną zignorowane, a cała jego powierzchnia zostanie wykorzystana do drukowania. Może to nie być obsługiwane przez Twoją drukarkę.</translation>
<translation>Jeżeli ta opcja jest zaznaczona, marginesy arkusza zostaną zignorowane, a cała jego powierzchnia zostanie wykorzystana do drukowania. Może to nie być obsługiwane przez Twoją drukarkę. </translation>
</message>
<message>
<location filename="../sources/print/projectprintwindow.ui" line="259"/>
@@ -5117,7 +5117,7 @@ Poniższe zmienne są zgodne:
<message>
<location filename="../sources/print/projectprintwindow.cpp" line="669"/>
<source>Exporter sous : </source>
<translation>Eksportuj jako: </translation>
<translation>Eksportuj jako:</translation>
</message>
<message>
<location filename="../sources/print/projectprintwindow.cpp" line="669"/>
@@ -6670,8 +6670,7 @@ Put DXFtoQET.exe binary on C:\Users\user_name\AppData\Roaming\qet\ directory
Odwiedź https://download.tuxfamily.org/qet/builds/dxf_to_elmt/
&gt;&gt; Instalacja w Windows
Przenieś DXFtoQET.exe binary do C:\Users\user_name\AppData\Roaming\qet\ directory
</translation>
Przenieś DXFtoQET.exe binary do C:\Users\user_name\AppData\Roaming\qet\ directory</translation>
</message>
<message>
<location filename="../sources/editor/qetelementeditor.cpp" line="169"/>
@@ -6685,8 +6684,7 @@ Put DXFtoQET.app binary on /Users/user_name/.qet/ directory
Odwiedź https://download.tuxfamily.org/qet/builds/dxf_to_elmt/
&gt;&gt; Instalacja w macOSX
Przenieś DXFtoQET.app binary do /Users/user_name/.qet/ directory
</translation>
Przenieś DXFtoQET.app binary do /Users/user_name/.qet/ directory</translation>
</message>
<message>
<location filename="../sources/editor/qetelementeditor.cpp" line="175"/>
@@ -6702,8 +6700,7 @@ Odwiedź https://download.tuxfamily.org/qet/builds/dxf_to_elmt/
&gt;&gt; Instalacja w Linux
Preznieś DXFtoQET binary do twojego /home/user_name/.qet/ directory
make it executable : chmod +x ./DXFtoQE
</translation>
make it executable : chmod +x ./DXFtoQE</translation>
</message>
<message>
<location filename="../sources/editor/qetelementeditor.cpp" line="295"/>
@@ -8776,14 +8773,14 @@ Czy chcesz ją zastąpić?</translation>
<source>Les information à afficher sont supérieurs à la quantité maximal pouvant être affiché par les tableaux.
Veuillez ajouter un nouveau tableau ou regler les tableaux existant afin d&apos;afficher l&apos;integralité des informations.</source>
<translation>Wyświetlane informacje większe niż maksymalna liczba, którą można wyświetlić w tabelach.
Dodaj nową tabelę lub dostosuj istniejące tabele, aby wyświetlić wszystkie informacje.</translation>
Dodaj nową tabelę lub dostosuj istniejące tabele, aby wyświetlić wszystkie informacje. </translation>
</message>
<message>
<location filename="../sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.cpp" line="118"/>
<source>Les information à afficher sont supérieurs à la quantité maximal pouvant être affiché par le tableau.
Veuillez ajouter un nouveau tableau ou regler le tableau existant afin d&apos;afficher l&apos;integralité des informations.</source>
<translation>Wyświetlane informacje większe niż maksymalna liczba, którą można wyświetlić w tabeli.
Dodaj nową tabelę lub dostosuj istniejącą, aby wyświetlić wszystkie informacje.</translation>
Dodaj nową tabelę lub dostosuj istniejącą, aby wyświetlić wszystkie informacje. </translation>
</message>
<message>
<location filename="../sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.cpp" line="121"/>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -331,7 +331,6 @@ void BorderTitleBlock::importTitleBlock(const TitleBlockProperties &ip) {
// through setFolioData(),
// which in turn calls updateDiagramContextForTitleBlock().
emit(needTitleBlockTemplate(ip.template_name));
emit informationChanged();
}
/**

View File

@@ -245,12 +245,6 @@ class BorderTitleBlock : public QObject
since it does not know of its parent project.
*/
void needTitleBlockTemplate(const QString &);
/**
* @brief infoChanged
* Signal emitted when the informations changed.
*/
void informationChanged();
// attributes
private:

View File

@@ -27,6 +27,7 @@
@param parent QWidget parent
*/
ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
Machine_info *mymachineinfo= new Machine_info(this);
//ScrollArea for low screens
QScrollArea *scroll = new QScrollArea(this);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
@@ -35,7 +36,7 @@ ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
// liste des pages
pages_list = new QListWidget();
pages_list -> setViewMode(QListView::IconMode);
if(MachineInfo::instance()->i_max_screen_height()<1000){
if(mymachineinfo->i_max_screen_height()<1000){
pages_list -> setIconSize(QSize(64, 64));
} else {
pages_list -> setIconSize(QSize(128, 128));
@@ -79,8 +80,8 @@ ConfigDialog::ConfigDialog(QWidget *parent) : QDialog(parent) {
connect(pages_list, SIGNAL(currentRowChanged(int)),
pages_widget, SLOT(setCurrentIndex(int)));
setMaximumSize(MachineInfo::instance()->i_max_screen_width(),
MachineInfo::instance()->i_max_screen_height());
setMaximumSize(mymachineinfo->i_max_screen_width(),
mymachineinfo->i_max_screen_height());
resize(1400,1000);
#ifdef Q_OS_MACOS

View File

@@ -157,41 +157,40 @@ void ElementQueryWidget::setQuery(const QString &query)
//Element type filter
if (where.contains("element_sub_type") || where.contains("element_type"))
{
QRegularExpression rx("^(\\( .+?\\))");
auto rxm = rx.match(where);
if (rxm.hasMatch())
{
auto str_type = rxm.captured(1);
where.remove(str_type);
int c=0;
ui->m_simple_cb->setChecked (str_type.contains("Simple") ? true : false);
if (ui->m_simple_cb->isChecked()) {
++c;
}
ui->m_terminal_cb->setChecked (str_type.contains("Terminale") ? true : false);
if (ui->m_terminal_cb->isChecked()) {
++c;
}
ui->m_coil_cb->setChecked (str_type.contains("coil") ? true : false);
if (ui->m_coil_cb->isChecked()) {
++c;
}
ui->m_button_cb->setChecked (str_type.contains("commutator") ? true : false);
if (ui->m_button_cb->isChecked()) {
++c;
}
ui->m_protection_cb->setChecked(str_type.contains("protection") ? true : false);
if (ui->m_protection_cb) {
++c;
}
if (c == 5) {
ui->m_all_cb->setCheckState(Qt::Checked);
} else if (c > 0) {
ui->m_all_cb->setCheckState(Qt::PartiallyChecked);
}
int c=0;
ui->m_simple_cb->setChecked (where.contains("Simple") ? true : false);
if (ui->m_simple_cb->isChecked()) {
++c;
where.remove("element_type = 'Simple' ");
}
ui->m_terminal_cb->setChecked (where.contains("Terminale") ? true : false);
if (ui->m_terminal_cb->isChecked()) {
++c;
where.remove("element_type = 'Terminale'");
}
ui->m_coil_cb->setChecked (where.contains("coil") ? true : false);
if (ui->m_coil_cb->isChecked()) {
++c;
where.remove("element_sub_type = 'coil' ");
}
ui->m_button_cb->setChecked (where.contains("commutator") ? true : false);
if (ui->m_button_cb->isChecked()) {
++c;
where.remove("element_sub_type = 'commutator' ");
}
ui->m_protection_cb->setChecked(where.contains("protection") ? true : false);
if (ui->m_protection_cb) {
++c;
where.remove("element_sub_type = 'protection'");
}
if (c == 5) {
ui->m_all_cb->setCheckState(Qt::Checked);
} else if (c > 0) {
ui->m_all_cb->setCheckState(Qt::PartiallyChecked);
}
where.remove("OR");
}
else // There is not "element_sub_type" or "element_type" that mean every element are selected
{
@@ -207,16 +206,20 @@ void ElementQueryWidget::setQuery(const QString &query)
strl.append(item->data(Qt::UserRole).toString());
}
QString join_str = strl.join("|");
QString beginning_rx;
beginning_rx.append(QString("^(").append(strl.join("|")));
beginning_rx.append(")");
QRegularExpression rx_is_not_null(beginning_rx + " IS NOT NULL$");
QRegularExpression rx_is_null (beginning_rx + " IS NULL$");
QRegularExpression rx_like (beginning_rx + QString(" LIKE'%(.+)%'$"));
QRegularExpression rx_not_like (beginning_rx + QString(" NOT LIKE'%(.+)%'$"));
QRegularExpression rx_equal (beginning_rx + QString("='(.+)'$"));
QRegularExpression rx_not_equal (beginning_rx + QString("!='(.+)'$"));
QRegularExpression rx_is_not_null(QStringLiteral("^(%1) != ''$").arg(join_str));
QRegularExpression rx_is_null (QStringLiteral("^\\((%1) IS NULL OR (%1) = ''\\)").arg(join_str));
QRegularExpression rx_like (QStringLiteral("^(%1) LIKE'%(.+)%'$").arg(join_str));
QRegularExpression rx_not_like (QStringLiteral("^(%1) NOT LIKE'%(.+)%'$").arg(join_str));
QRegularExpression rx_equal (QStringLiteral("^(%1)='(.+)'$").arg(join_str));
QRegularExpression rx_not_equal (QStringLiteral("^(%1)!='(.+)'$").arg(join_str));
QStringList split_where;
//Remove the white space at begin and end of each string
for (auto str : where.split("AND "))
{
@@ -307,22 +310,22 @@ QString ElementQueryWidget::queryStr() const
case 0: //No filter
break;
case 1: //Not empty
filter_ += QStringLiteral(" AND ") += key += " != ''";
filter_ += QString(" AND ") += key += " IS NOT NULL";
break;
case 2: //empty
filter_ += QStringLiteral(" AND (%1 IS NULL OR %1 = '')").arg(key);
filter_ += QString(" AND ") += key += " IS NULL";
break;
case 3: // contain
filter_ += QStringLiteral(" AND ") += key += QStringLiteral(" LIKE'%") += f.second += "%'";
filter_ += QString(" AND ") += key += QString(" LIKE'%") += f.second += "%'";
break;
case 4: // not contain
filter_ += QStringLiteral(" AND ") += key += QStringLiteral(" NOT LIKE'%") += f.second += "%'";
filter_ += QString(" AND ") += key += QString(" NOT LIKE'%") += f.second += "%'";
break;
case 5: // is equal
filter_ += QStringLiteral(" AND ") += key += QStringLiteral("='") += f.second += "'";
filter_ += QString(" AND ") += key += QString("='") += f.second += "'";
break;
case 6: // is not equal
filter_ += QStringLiteral(" AND ") += key += QStringLiteral("!='") += f.second += "'";
filter_ += QString(" AND ") += key += QString("!='") += f.second += "'";
break;
}
}

View File

@@ -92,9 +92,6 @@ Diagram::Diagram(QETProject *project) :
pen.setColor(Qt::black);
conductor_setter_ -> setPen(pen);
connect(&border_and_titleblock,
&BorderTitleBlock::informationChanged,
this, &Diagram::diagramInformationChanged);
connect(&border_and_titleblock,
&BorderTitleBlock::needTitleBlockTemplate,
this, &Diagram::setTitleBlockTemplate);
@@ -137,20 +134,15 @@ Diagram::~Diagram()
delete m_event_interface;
// list removable items
QVector<QGraphicsItem *> deletable_items;
for(const auto &qgi : items())
QList<QGraphicsItem *> deletable_items;
for(QGraphicsItem *qgi : items())
{
if (qgi->parentItem())
continue;
if (qgraphicsitem_cast<Conductor *>(qgi))
continue;
deletable_items.append(qgi);
}
for (const auto &item : qAsConst(deletable_items))
{
removeItem(item);
delete item;
if (qgi -> parentItem()) continue;
if (qgraphicsitem_cast<Conductor *>(qgi)) continue;
deletable_items << qgi;
}
qDeleteAll (deletable_items);
}
/**
@@ -197,12 +189,12 @@ void Diagram::drawBackground(QPainter *p, const QRectF &r) {
// If user allow zoom out beyond of folio,
// we draw grid outside of border.
QSettings settings;
int xGrid = settings.value(QStringLiteral("diagrameditor/Xgrid"),
Diagram::xGrid).toInt();
int yGrid = settings.value(QStringLiteral("diagrameditor/Ygrid"),
Diagram::yGrid).toInt();
int xGrid = settings.value("diagrameditor/Xgrid",
Diagram::xGrid).toInt();
int yGrid = settings.value("diagrameditor/Ygrid",
Diagram::yGrid).toInt();
QRectF rect = settings.value(
QStringLiteral("diagrameditor/zoom-out-beyond-of-folio"),
"diagrameditor/zoom-out-beyond-of-folio",
false).toBool() ? r
: border_and_titleblock
.insideBorderRect()
@@ -332,6 +324,15 @@ void Diagram::wheelEvent(QGraphicsSceneWheelEvent *event)
*/
void Diagram::keyPressEvent(QKeyEvent *event)
{
QSettings settings;
int xKeyGrid = settings.value("diagrameditor/key_Xgrid",
Diagram::xKeyGrid).toInt();
int yKeyGrid = settings.value("diagrameditor/key_Ygrid",
Diagram::yKeyGrid).toInt();
int xKeyGridFine = settings.value("diagrameditor/key_fine_Xgrid",
Diagram::xKeyGridFine).toInt();
int yKeyGridFine = settings.value("diagrameditor/key_fine_Ygrid",
Diagram::yKeyGridFine).toInt();
event->setAccepted(false);
if (m_event_interface) {
@@ -360,11 +361,6 @@ void Diagram::keyPressEvent(QKeyEvent *event)
//Move item with the keyboard arrow
if(event->modifiers() == Qt::NoModifier)
{
QSettings settings;
int xKeyGrid = settings.value(QStringLiteral("diagrameditor/key_Xgrid"),
Diagram::xKeyGrid).toInt();
int yKeyGrid = settings.value(QStringLiteral("diagrameditor/key_Ygrid"),
Diagram::yKeyGrid).toInt();
switch(event->key())
{
case Qt::Key_Left:
@@ -403,11 +399,6 @@ void Diagram::keyPressEvent(QKeyEvent *event)
}
else if(event->modifiers() == Qt::AltModifier)
{
QSettings settings;
int xKeyGridFine = settings.value(QStringLiteral("diagrameditor/key_fine_Xgrid"),
Diagram::xKeyGridFine).toInt();
int yKeyGridFine = settings.value(QStringLiteral("diagrameditor/key_fine_Ygrid"),
Diagram::yKeyGridFine).toInt();
switch(event->key())
{
case Qt::Key_Left:
@@ -741,7 +732,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
// XML tree root
// racine de l'arbre XML
auto dom_root = document.createElement(QStringLiteral("diagram"));
auto dom_root = document.createElement("diagram");
// schema properties
// proprietes du schema
@@ -751,24 +742,24 @@ QDomDocument Diagram::toXml(bool whole_content) {
// Default conductor properties
QDomElement default_conductor =
document.createElement(QStringLiteral("defaultconductor"));
document.createElement("defaultconductor");
defaultConductorProperties.toXml(default_conductor);
dom_root.appendChild(default_conductor);
// Conductor autonum
if (!m_conductors_autonum_name.isEmpty()) {
dom_root.setAttribute(QStringLiteral("conductorAutonum"),
dom_root.setAttribute("conductorAutonum",
m_conductors_autonum_name);
}
//Default New Element
dom_root.setAttribute(QStringLiteral("freezeNewElement"),
m_freeze_new_elements ? QStringLiteral("true") : QStringLiteral("false"));
dom_root.setAttribute("freezeNewElement",
m_freeze_new_elements ? "true" : "false");
//Default New Conductor
dom_root.setAttribute(QStringLiteral("freezeNewConductor"),
dom_root.setAttribute("freezeNewConductor",
m_freeze_new_conductors_
? QStringLiteral("true") : QStringLiteral("false"));
? "true" : "false");
//Element Folio Sequential Variables
if (!m_elmt_unitfolio_max.isEmpty()
@@ -776,37 +767,37 @@ QDomDocument Diagram::toXml(bool whole_content) {
|| !m_elmt_hundredfolio_max.isEmpty()) {
QDomElement elmtfoliosequential =
document.createElement(
QStringLiteral("elementautonumfoliosequentials"));
"elementautonumfoliosequentials");
if (!m_elmt_unitfolio_max.isEmpty()) {
QDomElement elmtfolioseq =
document.createElement(
QStringLiteral("elementunitfolioseq"));
"elementunitfolioseq");
folioSequentialsToXml(&m_elmt_unitfolio_max,
&elmtfolioseq,
QStringLiteral("sequf_"),
QStringLiteral("unitfolioseq"),
"sequf_",
"unitfolioseq",
&document);
elmtfoliosequential.appendChild(elmtfolioseq);
}
if (!m_elmt_tenfolio_max.isEmpty()) {
QDomElement elmtfolioseq =
document.createElement(
QStringLiteral("elementtenfolioseq"));
"elementtenfolioseq");
folioSequentialsToXml(&m_elmt_tenfolio_max,
&elmtfolioseq,
QStringLiteral("seqtf_"),
QStringLiteral("tenfolioseq"),
"seqtf_",
"tenfolioseq",
&document);
elmtfoliosequential.appendChild(elmtfolioseq);
}
if (!m_elmt_hundredfolio_max.isEmpty()) {
QDomElement elmtfolioseq =
document.createElement(
QStringLiteral("elementhundredfolioseq"));
"elementhundredfolioseq");
folioSequentialsToXml(&m_elmt_hundredfolio_max,
&elmtfolioseq,
QStringLiteral("seqhf_"),
QStringLiteral("hundredfolioseq"),
"seqhf_",
"hundredfolioseq",
&document);
elmtfoliosequential.appendChild(elmtfolioseq);
}
@@ -818,38 +809,38 @@ QDomDocument Diagram::toXml(bool whole_content) {
!m_cnd_hundredfolio_max.isEmpty()) {
QDomElement cndfoliosequential =
document.createElement(
QStringLiteral("conductorautonumfoliosequentials"));
"conductorautonumfoliosequentials");
QHash<QString, QStringList>::iterator i;
if (!m_cnd_unitfolio_max.isEmpty()) {
QDomElement cndfolioseq =
document.createElement(
QStringLiteral("conductorunitfolioseq"));
"conductorunitfolioseq");
folioSequentialsToXml(&m_cnd_unitfolio_max,
&cndfolioseq,
QStringLiteral("sequf_"),
QStringLiteral("unitfolioseq"),
"sequf_",
"unitfolioseq",
&document);
cndfoliosequential.appendChild(cndfolioseq);
}
if (!m_cnd_tenfolio_max.isEmpty()) {
QDomElement cndfolioseq =
document.createElement(
QStringLiteral("conductortenfolioseq"));
"conductortenfolioseq");
folioSequentialsToXml(&m_cnd_tenfolio_max,
&cndfolioseq,
QStringLiteral("seqtf_"),
QStringLiteral("tenfolioseq"),
"seqtf_",
"tenfolioseq",
&document);
cndfoliosequential.appendChild(cndfolioseq);
}
if (!m_cnd_hundredfolio_max.isEmpty()) {
QDomElement cndfolioseq =
document.createElement(
QStringLiteral("conductorhundredfolioseq"));
"conductorhundredfolioseq");
folioSequentialsToXml(&m_cnd_hundredfolio_max,
&cndfolioseq,
QStringLiteral("seqhf_"),
QStringLiteral("hundredfolioseq"),
"seqhf_",
"hundredfolioseq",
&document);
cndfoliosequential.appendChild(cndfolioseq);
}
@@ -860,7 +851,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
//this method with whole_content to false,
//is often use to copy and paste the current selection
//so we add the id of the project where copy occur.
dom_root.setAttribute(QStringLiteral("projectId"), QETApp::projectId(m_project));
dom_root.setAttribute("projectId", QETApp::projectId(m_project));
}
document.appendChild(dom_root);
@@ -930,7 +921,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
QHash<Terminal *, int> table_adr_id;
if (!list_elements.isEmpty()) {
auto dom_elements = document.createElement(QStringLiteral("elements"));
auto dom_elements = document.createElement("elements");
for (auto elmt : list_elements) {
dom_elements.appendChild(elmt->toXml(document,
table_adr_id));
@@ -939,7 +930,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
}
if (!list_conductors.isEmpty()) {
auto dom_conductors = document.createElement(QStringLiteral("conductors"));
auto dom_conductors = document.createElement("conductors");
for (auto cond : list_conductors) {
dom_conductors.appendChild(cond->toXml(document,
table_adr_id));
@@ -948,7 +939,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
}
if (!list_texts.isEmpty()) {
auto dom_texts = document.createElement(QStringLiteral("inputs"));
auto dom_texts = document.createElement("inputs");
for (auto dti : list_texts) {
dom_texts.appendChild(dti->toXml(document));
}
@@ -956,7 +947,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
}
if (!list_images.isEmpty()) {
auto dom_images = document.createElement(QStringLiteral("images"));
auto dom_images = document.createElement("images");
for (auto dii : list_images) {
dom_images.appendChild(dii->toXml(document));
}
@@ -964,7 +955,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
}
if (!list_shapes.isEmpty()) {
auto dom_shapes = document.createElement(QStringLiteral("shapes"));
auto dom_shapes = document.createElement("shapes");
for (auto dii : list_shapes) {
dom_shapes.appendChild(dii -> toXml(document));
}
@@ -972,7 +963,7 @@ QDomDocument Diagram::toXml(bool whole_content) {
}
if (table_vector.size()) {
auto tables = document.createElement(QStringLiteral("tables"));
auto tables = document.createElement("tables");
for (auto table : table_vector) {
tables.appendChild(table->toXml(document));
}
@@ -996,15 +987,11 @@ void Diagram::folioSequentialsToXml(QHash<QString,
QDomElement *domElement,
const QString& seq_type,
const QString& type,
QDomDocument *doc)
{
QDomDocument *doc) {
QHash<QString, QStringList>::iterator i;
for (i = hash->begin(); i != hash->end(); i++)
{
for (i = hash->begin(); i != hash->end(); i++) {
QDomElement folioseq = doc->createElement(type);
folioseq.setAttribute(QStringLiteral("title"), i.key());
folioseq.setAttribute("title", i.key());
for (int j = 0; j < i.value().size(); j++) {
folioseq.setAttribute(seq_type + QString::number(j+1),
i.value().at(j));
@@ -1109,15 +1096,14 @@ bool Diagram::initFromXml(QDomElement &document,
@return
*/
Terminal* findTerminal(int conductor_index,
QDomElement& f,
QHash<int,Terminal *>& table_adr_id,
QList<Element *>& added_elements)
{
QDomElement& f,
QHash<int,
Terminal *>& table_adr_id,
QList<Element *>& added_elements) {
assert(conductor_index == 1 || conductor_index == 2);
auto str_index = QString::number(conductor_index);
QString element_index = QStringLiteral("element") + str_index;
QString terminal_index = QStringLiteral("terminal") + str_index;
QString element_index = "element" + QString::number(conductor_index);
QString terminal_index = "terminal" + QString::number(conductor_index);
if (f.hasAttribute(element_index)) {
QUuid element_uuid = QUuid(f.attribute(element_index));
@@ -1199,13 +1185,10 @@ Terminal* findTerminal(int conductor_index,
bool Diagram::fromXml(QDomElement &document,
QPointF position,
bool consider_informations,
DiagramContent *content_ptr)
{
DiagramContent *content_ptr) {
const QDomElement& root = document;
// The first element must be a diagram
if (root.tagName() != QLatin1String("diagram")) {
return(false);
}
// The first element must be a diagram
if (root.tagName() != "diagram") return(false);
// Read attributes of this diagram
if (consider_informations)
@@ -1214,57 +1197,56 @@ bool Diagram::fromXml(QDomElement &document,
border_and_titleblock.titleBlockFromXml(root);
border_and_titleblock.borderFromXml(root);
// Find the element "defaultconductor".
// If found, load default conductor properties.
// Find the element "defaultconductor".
// If found, load default conductor properties.
QDomElement default_conductor_elmt =
root.firstChildElement(QStringLiteral("defaultconductor"));
root.firstChildElement("defaultconductor");
if (!default_conductor_elmt.isNull()) {
defaultConductorProperties.fromXml(default_conductor_elmt);
}
// Load the autonum
m_conductors_autonum_name = root.attribute(QStringLiteral("conductorAutonum"));
// Load the autonum
m_conductors_autonum_name = root.attribute("conductorAutonum");
// Load Freeze New Element
m_freeze_new_elements = root.attribute(QStringLiteral("freezeNewElement")).toInt();
// Load Freeze New Element
m_freeze_new_elements = root.attribute("freezeNewElement").toInt();
// Load Freeze New Conductor
m_freeze_new_conductors_ = root.attribute(QStringLiteral("freezeNewConductor")).toInt();
// Load Freeze New Conductor
m_freeze_new_conductors_ = root.attribute("freezeNewConductor").toInt();
//Load Element Folio Sequential
//Load Element Folio Sequential
folioSequentialsFromXml(root,
&m_elmt_unitfolio_max,
QStringLiteral("elementunitfolioseq"),
QStringLiteral("sequf_"),
QStringLiteral("unitfolioseq"),
QStringLiteral("elementautonumfoliosequentials"));
"elementunitfolioseq",
"sequf_",
"unitfolioseq",
"elementautonumfoliosequentials");
folioSequentialsFromXml(root, &m_elmt_tenfolio_max,
QStringLiteral("elementtenfolioseq"),
QStringLiteral("seqtf_"),
QStringLiteral("tenfolioseq"),
QStringLiteral("elementautonumfoliosequentials"));
"elementtenfolioseq",
"seqtf_",
"tenfolioseq",
"elementautonumfoliosequentials");
folioSequentialsFromXml(root, &m_elmt_hundredfolio_max,
QStringLiteral("elementhundredfolioseq"),
QStringLiteral("seqhf_"),
QStringLiteral("hundredfolioseq"),
QStringLiteral("elementautonumfoliosequentials"));
"elementhundredfolioseq",
"seqhf_",
"hundredfolioseq",
"elementautonumfoliosequentials");
//Load Conductor Folio Sequential
//Load Conductor Folio Sequential
folioSequentialsFromXml(root, &m_cnd_unitfolio_max,
QStringLiteral("conductorunitfolioseq"),
QStringLiteral("sequf_"),
QStringLiteral("unitfolioseq"),
QStringLiteral("conductorautonumfoliosequentials"));
"conductorunitfolioseq",
"sequf_",
"unitfolioseq",
"conductorautonumfoliosequentials");
folioSequentialsFromXml(root, &m_cnd_tenfolio_max,
QStringLiteral("conductortenfolioseq"),
QStringLiteral("seqtf_"),
QStringLiteral("tenfolioseq"),
QStringLiteral("conductorautonumfoliosequentials"));
"conductortenfolioseq",
"seqtf_","tenfolioseq",
"conductorautonumfoliosequentials");
folioSequentialsFromXml(root, &m_cnd_hundredfolio_max,
QStringLiteral("conductorhundredfolioseq"),
QStringLiteral("seqhf_"),
QStringLiteral("hundredfolioseq"),
QStringLiteral("conductorautonumfoliosequentials"));
"conductorhundredfolioseq",
"seqhf_",
"hundredfolioseq",
"conductorautonumfoliosequentials");
}
// if child haven't got a child, loading is finish (diagram is empty)
@@ -1273,10 +1255,10 @@ bool Diagram::fromXml(QDomElement &document,
}
//If paste from another project
if (root.hasAttribute(QStringLiteral("projectId")))
{
QETProject *other_project = QETApp::project(root.attribute(QStringLiteral("projectId"),
QStringLiteral("-1")).toInt());
if (root.hasAttribute("projectId")) {
QETProject *other_project = QETApp::project(
root.attribute("projectId",
"-1").toInt());
/* We try to paste from another project,
* then befor paste elements,
@@ -1284,18 +1266,17 @@ bool Diagram::fromXml(QDomElement &document,
* (owned by other project)
* in the embedded collection of this project
*/
if (other_project && other_project != m_project)
{
if (other_project && other_project != m_project) {
ElementCollectionHandler ech;
for (auto element_xml :
foreach (QDomElement element_xml,
QET::findInDomElement(root,
QStringLiteral("elements"),
QStringLiteral("element"))) {
"elements",
"element")) {
if (!Element::valideXml(element_xml)) continue;
QString type_id = element_xml.attribute(QStringLiteral("type"));
QString type_id = element_xml.attribute("type");
if (type_id.startsWith(QStringLiteral("embed://"))) {
if (type_id.startsWith("embed://")) {
ElementsLocation location(
type_id,
other_project);
@@ -1308,15 +1289,15 @@ bool Diagram::fromXml(QDomElement &document,
//Load all elements from the XML
QList<Element *> added_elements;
QHash<int, Terminal *> table_adr_id;
for (auto element_xml :
QET::findInDomElement(root, QStringLiteral("elements"), QStringLiteral("element")))
foreach (QDomElement element_xml,
QET::findInDomElement(root, "elements", "element"))
{
if (!Element::valideXml(element_xml)) continue;
// cree un element dont le type correspond a l'id type
QString type_id = element_xml.attribute(QStringLiteral("type"));
QString type_id = element_xml.attribute("type");
ElementsLocation element_location;
if (type_id.startsWith(QStringLiteral("embed://"))) {
if (type_id.startsWith("embed://")) {
element_location = ElementsLocation(type_id, m_project);
}
else {
@@ -1345,7 +1326,8 @@ bool Diagram::fromXml(QDomElement &document,
{
removeItem(nvel_elmt);
delete nvel_elmt;
qDebug() << QStringLiteral("Diagram::fromXml() : Le chargement des parametres d'un element a echoue");
qDebug() << "Diagram::fromXml() : Le chargement des "
"parametres d'un element a echoue";
} else {
added_elements << nvel_elmt;
}
@@ -1353,9 +1335,9 @@ bool Diagram::fromXml(QDomElement &document,
// Load text
QList<IndependentTextItem *> added_texts;
for (auto text_xml : QET::findInDomElement(root,
QStringLiteral("inputs"),
QStringLiteral("input"))) {
foreach (QDomElement text_xml, QET::findInDomElement(root,
"inputs",
"input")) {
IndependentTextItem *iti = new IndependentTextItem();
iti -> fromXml(text_xml);
addItem(iti);
@@ -1364,9 +1346,9 @@ bool Diagram::fromXml(QDomElement &document,
// Load image
QList<DiagramImageItem *> added_images;
for (auto image_xml : QET::findInDomElement(root,
QStringLiteral("images"),
QStringLiteral("image"))) {
foreach (QDomElement image_xml, QET::findInDomElement(root,
"images",
"image")) {
DiagramImageItem *dii = new DiagramImageItem ();
dii -> fromXml(image_xml);
addItem(dii);
@@ -1375,9 +1357,9 @@ bool Diagram::fromXml(QDomElement &document,
// Load shape
QList<QetShapeItem *> added_shapes;
for (auto shape_xml : QET::findInDomElement(root,
QStringLiteral("shapes"),
QStringLiteral("shape"))) {
foreach (QDomElement shape_xml, QET::findInDomElement(root,
"shapes",
"shape")) {
QetShapeItem *dii = new QetShapeItem (QPointF(0,0));
dii -> fromXml(shape_xml);
addItem(dii);
@@ -1386,9 +1368,9 @@ bool Diagram::fromXml(QDomElement &document,
// Load conductor
QList<Conductor *> added_conductors;
for (auto f : QET::findInDomElement(root,
QStringLiteral("conductors"),
QStringLiteral("conductor")))
foreach (QDomElement f, QET::findInDomElement(root,
"conductors",
"conductor"))
{
if (!Conductor::valideXml(f)) continue;
@@ -1413,9 +1395,10 @@ bool Diagram::fromXml(QDomElement &document,
//Load tables
QVector<QetGraphicsTableItem *> added_tables;
for (const auto &dom_table : QETXML::subChild(root,
QStringLiteral("tables"),
QetGraphicsTableItem::xmlTagName()))
for (auto dom_table
: QETXML::subChild(root,
"tables",
QetGraphicsTableItem::xmlTagName()))
{
auto table = new QetGraphicsTableItem();
addItem(table);
@@ -1427,12 +1410,12 @@ bool Diagram::fromXml(QDomElement &document,
if (position != QPointF())
{
QVector <QGraphicsItem *> added_items;
for (auto element : qAsConst(added_elements )) added_items << element;
for (auto cond : qAsConst(added_conductors )) added_items << cond;
for (auto shape : qAsConst(added_shapes )) added_items << shape;
for (auto text : qAsConst(added_texts )) added_items << text;
for (auto image : qAsConst(added_images )) added_items << image;
for (auto table : qAsConst(added_tables )) added_items << table;
for (auto element : added_elements ) added_items << element;
for (auto cond : added_conductors) added_items << cond;
for (auto shape : added_shapes ) added_items << shape;
for (auto text : added_texts ) added_items << text;
for (auto image : added_images ) added_items << image;
for (auto table : added_tables ) added_items << table;
//Get the top left corner of the rectangle that contain all added items
QRectF items_rect;
@@ -1504,7 +1487,7 @@ void Diagram::folioSequentialsFromXml(const QDomElement &root,
= folioSeqAutoNum.firstChildElement(type);
!folioseq.isNull();
folioseq = folioseq.nextSiblingElement(type)) {
QString title = folioseq.attribute(QStringLiteral("title"));
QString title = folioseq.attribute("title");
QStringList list;
int i = 1;
while (folioseq.hasAttribute(seq
@@ -1888,10 +1871,10 @@ void Diagram::loadElmtFolioSeq()
|| !m_elmt_unitfolio_max.contains(title)) {
//Insert Initial Value
if (project()->elementAutoNumCurrentFormula().contains(
QStringLiteral("%sequf_"))) {
"%sequf_")) {
insertFolioSeqHash(&m_elmt_unitfolio_max,
title,
QStringLiteral("unitfolio"),
"unitfolio",
&nc);
project()->addElementAutoNum(title,nc);
}
@@ -1899,10 +1882,10 @@ void Diagram::loadElmtFolioSeq()
else if (m_elmt_unitfolio_max.contains(title)) {
//Load Folio Current Value
if (project()->elementAutoNumCurrentFormula().contains(
QStringLiteral("%sequf_"))) {
"%sequf_")) {
loadFolioSeqHash(&m_elmt_unitfolio_max,
title,
QStringLiteral("unitfolio"),
"unitfolio",
&nc);
project()->addElementAutoNum(title,nc);
}
@@ -1913,10 +1896,10 @@ void Diagram::loadElmtFolioSeq()
|| !m_elmt_tenfolio_max.contains(title)) {
//Insert Initial Value
if (project()->elementAutoNumCurrentFormula().contains(
QStringLiteral("%seqtf_"))) {
"%seqtf_")) {
insertFolioSeqHash(&m_elmt_tenfolio_max,
title,
QStringLiteral("tenfolio"),
"tenfolio",
&nc);
project()->addElementAutoNum(title,nc);
}
@@ -1924,10 +1907,10 @@ void Diagram::loadElmtFolioSeq()
else if (m_elmt_tenfolio_max.contains(title)) {
//Load Folio Current Value
if (project()->elementAutoNumCurrentFormula().contains(
QStringLiteral("%seqtf_"))) {
"%seqtf_")) {
loadFolioSeqHash(&m_elmt_tenfolio_max,
title,
QStringLiteral("tenfolio"),
"tenfolio",
&nc);
project()->addElementAutoNum(title,nc);
}
@@ -1938,10 +1921,10 @@ void Diagram::loadElmtFolioSeq()
|| !m_elmt_hundredfolio_max.contains(title)) {
//Insert Initial Value
if (project()->elementAutoNumCurrentFormula().contains(
QStringLiteral("%seqhf_"))) {
"%seqhf_")) {
insertFolioSeqHash(&m_elmt_hundredfolio_max,
title,
QStringLiteral("hundredfolio"),
"hundredfolio",
&nc);
project()->addElementAutoNum(title,nc);
}
@@ -1949,10 +1932,10 @@ void Diagram::loadElmtFolioSeq()
else if (m_elmt_hundredfolio_max.contains(title)) {
//Load Folio Current Value
if (project()->elementAutoNumCurrentFormula().contains(
QStringLiteral("%seqhf_"))) {
"%seqhf_")) {
loadFolioSeqHash(&m_elmt_hundredfolio_max,
title,
QStringLiteral("hundredfolio"),
"hundredfolio",
&nc);
project()->addElementAutoNum(title,nc);
}
@@ -1975,20 +1958,20 @@ void Diagram::loadCndFolioSeq()
if (m_cnd_unitfolio_max.isEmpty()
|| !m_cnd_unitfolio_max.contains(title)) {
//Insert Initial Value
if (formula.contains(QStringLiteral("%sequf_"))) {
if (formula.contains("%sequf_")) {
insertFolioSeqHash(&m_cnd_unitfolio_max,
title,
QStringLiteral("unitfolio"),
"unitfolio",
&nc);
project()->addConductorAutoNum(title,nc);
}
}
else if (m_cnd_unitfolio_max.contains(title)) {
//Load Folio Current Value
if (formula.contains(QStringLiteral("%sequf_"))) {
if (formula.contains("%sequf_")) {
loadFolioSeqHash(&m_cnd_unitfolio_max,
title,
QStringLiteral("unitfolio"),
"unitfolio",
&nc);
project()->addConductorAutoNum(title,nc);
}
@@ -1998,20 +1981,20 @@ void Diagram::loadCndFolioSeq()
if (m_cnd_tenfolio_max.isEmpty()
|| !m_cnd_tenfolio_max.contains(title)) {
//Insert Initial Value
if (formula.contains(QStringLiteral("%seqtf_"))) {
if (formula.contains("%seqtf_")) {
insertFolioSeqHash(&m_cnd_tenfolio_max,
title,
QStringLiteral("tenfolio"),
"tenfolio",
&nc);
project()->addConductorAutoNum(title,nc);
}
}
else if (m_cnd_tenfolio_max.contains(title)) {
//Load Folio Current Value
if (formula.contains(QStringLiteral("%seqtf_"))) {
if (formula.contains("%seqtf_")) {
loadFolioSeqHash(&m_cnd_tenfolio_max,
title,
QStringLiteral("tenfolio"),
"tenfolio",
&nc);
project()->addConductorAutoNum(title,nc);
}
@@ -2021,20 +2004,20 @@ void Diagram::loadCndFolioSeq()
if (m_cnd_hundredfolio_max.isEmpty()
|| !m_cnd_hundredfolio_max.contains(title)) {
//Insert Initial Value
if (formula.contains(QStringLiteral("%seqhf_"))) {
if (formula.contains("%seqhf_")) {
insertFolioSeqHash(&m_cnd_hundredfolio_max,
title,
QStringLiteral("hundredfolio"),
"hundredfolio",
&nc);
project()->addConductorAutoNum(title,nc);
}
}
else if (m_cnd_hundredfolio_max.contains(title)) {
//Load Folio Current Value
if (formula.contains(QStringLiteral("%seqhf_"))) {
if (formula.contains("%seqhf_")) {
loadFolioSeqHash(&m_cnd_hundredfolio_max,
title,
QStringLiteral("hundredfolio"),
"hundredfolio",
&nc);
project()->addConductorAutoNum(title,nc);
}
@@ -2274,10 +2257,10 @@ DiagramPosition Diagram::convertPosition(const QPointF &pos) {
QPointF Diagram::snapToGrid(const QPointF &p)
{
QSettings settings;
int xGrid = settings.value(QStringLiteral("diagrameditor/Xgrid"),
Diagram::xGrid).toInt();
int yGrid = settings.value(QStringLiteral("diagrameditor/Ygrid"),
Diagram::yGrid).toInt();
int xGrid = settings.value("diagrameditor/Xgrid",
Diagram::xGrid).toInt();
int yGrid = settings.value("diagrameditor/Ygrid",
Diagram::yGrid).toInt();
//Return a point rounded to the nearest pixel
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
@@ -2347,8 +2330,8 @@ QSet<Conductor *> Diagram::selectedConductors() const
bool Diagram::clipboardMayContainDiagram()
{
QString clipboard_text = QApplication::clipboard() -> text().trimmed();
bool may_be_diagram = clipboard_text.startsWith(QStringLiteral("<diagram"))
&& clipboard_text.endsWith(QStringLiteral("</diagram>"));
bool may_be_diagram = clipboard_text.startsWith("<diagram")
&& clipboard_text.endsWith("</diagram>");
return(may_be_diagram);
}

View File

@@ -283,7 +283,6 @@ class Diagram : public QGraphicsScene
void findElementRequired(const ElementsLocation &);
void diagramActivated();
void diagramInformationChanged();
};
Q_DECLARE_METATYPE(Diagram *)

View File

@@ -501,7 +501,7 @@ void DiagramView::mousePressEvent(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;
// Drag the view
@@ -1219,20 +1219,13 @@ QList<QAction *> DiagramView::contextMenuActions() const
*/
void DiagramView::contextMenuEvent(QContextMenuEvent *e)
{
if (auto qgi = m_diagram->itemAt(mapToScene(e->pos()), transform()))
if (QGraphicsItem *qgi = m_diagram->itemAt(mapToScene(e->pos()), transform()))
{
if (!qgi->isSelected()) {
if (!qgi -> isSelected()) {
m_diagram->clearSelection();
}
// At this step qgi can be deleted for exemple if qgi is a QetGraphicsHandlerItem.
// When we call clearSelection the parent item of the handler
// is deselected and so delete all handlers, in this case,
// qgi become a dangling pointer.
// we need to call again itemAt.
if (auto item_ = m_diagram->itemAt(mapToScene(e->pos()), transform())) {
item_->setSelected(true);
}
qgi->setSelected(true);
}
if (m_diagram->selectedItems().isEmpty())

View File

@@ -1308,29 +1308,14 @@ void CustomElementGraphicPart::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
void CustomElementGraphicPart::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
if(event->button() == Qt::LeftButton)
m_origin_pos = this->pos();
m_first_move = true;
}
QGraphicsObject::mousePressEvent(event);
}
void CustomElementGraphicPart::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
//m_first_move is used to avoid an unwanted behavior
//when the properties dock widget is displayed :
//1 there is no selection
//2 the dock widget width is set to minimum
//3 select a part, the dock widget gain new widgets used to edit
//the current selected part and the width of the dock grow
//so the width of the QGraphicsView is reduced and cause a mouse move event.
//When this case occur the part is moved but they should not. This bool fix it.
if (Q_UNLIKELY(m_first_move)) {
m_first_move = false;
return;
}
if((event->buttons() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable))
{
QPointF pos = event->scenePos() + (m_origin_pos - event->buttonDownScenePos(Qt::LeftButton));

View File

@@ -328,7 +328,6 @@ class CustomElementGraphicPart : public QGraphicsObject, public CustomElementPar
Color _color;
bool _antialiased;
QPointF m_origin_pos;
bool m_first_move;
};
typedef CustomElementGraphicPart CEGP;

View File

@@ -389,12 +389,12 @@ StyleEditor::StyleEditor(QETElementEditor *editor, CustomElementGraphicPart *p,
auto grid_layout = new QGridLayout(this);
grid_layout->addWidget(new QLabel(tr("Contour :")), 0,0, Qt::AlignRight);
grid_layout->addWidget(outline_color, 0, 1);
grid_layout->addWidget(new QLabel(tr("Remplissage :")), 1, 0, Qt::AlignRight);
grid_layout->addWidget(filling_color, 1, 1);
grid_layout->addWidget(new QLabel(tr("Style :")), 2, 0, Qt::AlignRight);
grid_layout->addWidget(line_style, 2, 1);
grid_layout->addWidget(new QLabel(tr("Épaisseur :")), 3, 0, Qt::AlignRight);
grid_layout->addWidget(size_weight, 3 ,1);
grid_layout->addWidget(new QLabel(tr("Remplissage :")), 0, 2, Qt::AlignRight);
grid_layout->addWidget(filling_color, 0, 3);
grid_layout->addWidget(new QLabel(tr("Style :")), 1, 0, Qt::AlignRight);
grid_layout->addWidget(line_style, 1, 1);
grid_layout->addWidget(new QLabel(tr("Épaisseur :")), 1, 2, Qt::AlignRight);
grid_layout->addWidget(size_weight, 1 ,3);
main_layout->addItem(grid_layout);
main_layout -> addWidget(antialiasing);

View File

@@ -79,9 +79,10 @@ void QetGraphicsTableFactory::create(Diagram *diagram, AddTableDialog *dialog)
}
//Add new table if needed and option checked
if (dialog->addNewTableToNewDiagram()
&& table_->displayNRow() > 0
&& table_->model()->rowCount() > table_->displayNRow())
dialog->addNewTableToNewDiagram();
table_->model()->rowCount();
table_->displayNRow();
if (dialog->addNewTableToNewDiagram() && table_->model()->rowCount() > table_->displayNRow())
{
auto already_displayed_rows = table_->displayNRow();
auto project_ = diagram->project();

View File

@@ -29,21 +29,20 @@
#endif
#include "qet.h"
MachineInfo *MachineInfo::m_instance = nullptr;
/**
@brief MachineInfo::MachineInfo
@brief Machine_info::Machine_info
@param parent
*/
MachineInfo::MachineInfo()
Machine_info::Machine_info(QObject *parent) : QObject(parent)
{
init_get_Screen_info();
init_get_cpu_info();
}
/**
@brief MachineInfo::send_info_to_debug
@brief Machine_info::send_info_to_debug
*/
void MachineInfo::send_info_to_debug()
void Machine_info::send_info_to_debug()
{
qInfo()<<"debugging enabled:"
<< QLibraryInfo::isDebugBuild();
@@ -121,7 +120,7 @@ void MachineInfo::send_info_to_debug()
#endif
qInfo() << "GitRevision " + QString(GIT_COMMIT_SHA);
qInfo()<< "QElectroTech V " + QET::displayedVersion;
qInfo()<< QObject::tr("Compilation : ") + pc.built.version;
qInfo()<< tr("Compilation : ") + pc.built.version;
qInfo()<< "Built with Qt " + pc.built.QT
+ " - Date : " + pc.built.date
+ " : " + pc.built.time;
@@ -152,10 +151,10 @@ void MachineInfo::send_info_to_debug()
}
/**
@brief MachineInfo::init_get_Screen_info
@brief Machine_info::init_get_Screen_info
Finds the largest screen and saves the values
*/
void MachineInfo::init_get_Screen_info()
void Machine_info::init_get_Screen_info()
{
const auto screens = qApp->screens();
pc.screen.count=screens.count();
@@ -175,9 +174,9 @@ void MachineInfo::init_get_Screen_info()
}
/**
@brief MachineInfo::init_get_cpu_info
@brief Machine_info::init_get_cpu_info
*/
void MachineInfo::init_get_cpu_info()
void Machine_info::init_get_cpu_info()
{
#ifdef __GNUC__
#ifdef __APPLE_CC__
@@ -192,9 +191,9 @@ void MachineInfo::init_get_cpu_info()
}
/**
@brief MachineInfo::init_get_cpu_info_linux
@brief Machine_info::init_get_cpu_info_linux
*/
void MachineInfo::init_get_cpu_info_linux()
void Machine_info::init_get_cpu_info_linux()
{
QProcess linuxcpuinfo;
linuxcpuinfo.start("bash", QStringList()
@@ -238,9 +237,9 @@ void MachineInfo::init_get_cpu_info_linux()
}
/**
@brief MachineInfo::init_get_cpu_info_winnt
@brief Machine_info::init_get_cpu_info_winnt
*/
void MachineInfo::init_get_cpu_info_winnt()
void Machine_info::init_get_cpu_info_winnt()
{
QProcess wincpuinfo;
wincpuinfo.start("wmic",
@@ -292,9 +291,9 @@ void MachineInfo::init_get_cpu_info_winnt()
}
/**
@brief MachineInfo::init_get_cpu_info_macos
@brief Machine_info::init_get_cpu_info_macos
*/
void MachineInfo::init_get_cpu_info_macos()
void Machine_info::init_get_cpu_info_macos()
{
QProcess macoscpuinfo;
macoscpuinfo.start("bash",
@@ -318,28 +317,30 @@ void MachineInfo::init_get_cpu_info_macos()
}
/**
@brief MachineInfo::i_max_screen_width
@brief Machine_info::i_max_screen_width
@return max screen width
*/
int32_t MachineInfo::i_max_screen_width() {
int32_t Machine_info::i_max_screen_width()
{
return pc.screen.Max_width;
}
/**
@brief MachineInfo::i_max_screen_height
@brief Machine_info::i_max_screen_height
@return max screen height
*/
int32_t MachineInfo::i_max_screen_height() {
int32_t Machine_info::i_max_screen_height()
{
return pc.screen.Max_height;
}
/**
@brief MachineInfo::compilation_info
@brief Machine_info::compilation_info
@return compilation_info
*/
QString MachineInfo::compilation_info()
QString Machine_info::compilation_info()
{
QString compilation_info = "<br />" + QObject::tr("Compilation : ");
QString compilation_info = "<br />" + tr("Compilation : ");
compilation_info +=pc.built.version;
compilation_info += "<br>Built with Qt " + pc.built.QT;
compilation_info += " - Date : " + pc.built.date;

View File

@@ -18,57 +18,31 @@
#ifndef MACHINE_INFO_H
#define MACHINE_INFO_H
#include <QObject>
#include <QThread>
#include <QMutex>
/**
@brief The MachineInfo class
@brief The Machine_info class
This class hold information from your PC.
*/
class MachineInfo
class Machine_info : public QObject
{
static MachineInfo *m_instance;
public:
static MachineInfo *instance()
{
static QMutex mutex;
if (!m_instance)
{
mutex.lock();
if (!m_instance) {
m_instance = new MachineInfo();
}
mutex.unlock();
}
Q_OBJECT
public:
explicit Machine_info(QObject *parent = nullptr);
int32_t i_max_screen_width();
int32_t i_max_screen_height();
QString compilation_info();
void send_info_to_debug();
return m_instance;
}
static void dropInstance()
{
static QMutex mutex;
if (m_instance) {
mutex.lock();
delete m_instance;
m_instance = nullptr;
mutex.unlock();
}
}
int32_t i_max_screen_width();
int32_t i_max_screen_height();
QString compilation_info();
void send_info_to_debug();
private:
MachineInfo();
void init_get_Screen_info();
void init_get_cpu_info();
void init_get_cpu_info_linux();
void init_get_cpu_info_winnt();
void init_get_cpu_info_macos();
signals:
private:
void init_get_Screen_info();
void init_get_cpu_info();
void init_get_cpu_info_linux();
void init_get_cpu_info_winnt();
void init_get_cpu_info_macos();
struct Pc
{
struct Screen

View File

@@ -22,7 +22,6 @@
#include "utils/macosxopenevent.h"
#include <QStyleFactory>
#include <QtConcurrent>
/**
@brief myMessageOutput
@@ -201,15 +200,16 @@ int main(int argc, char **argv)
QObject::connect(&app, &SingleApplication::receivedMessage,
&qetapp, &QETApp::receiveMessage);
QtConcurrent::run([=]()
{
// for debugging
qInstallMessageHandler(myMessageOutput);
qInfo("Start-up");
// delete old log files of max 7 days old.
delete_old_log_files(7);
MachineInfo::instance()->send_info_to_debug();
});
// for debugging
qInstallMessageHandler(myMessageOutput);
qInfo("Start-up");
// delete old log files of max 7 days old.
delete_old_log_files(7);
{
Machine_info *my_ma =new Machine_info();
my_ma->send_info_to_debug();
delete my_ma;
}
return app.exec();
}

View File

@@ -95,13 +95,13 @@ void ProjectPrintWindow::launchDialog(QETProject *project, QPrinter::OutputForma
QString ProjectPrintWindow::docName(QETProject *project)
{
QString doc_name;
if (!project->filePath().isEmpty()) {
doc_name = QFileInfo(project->filePath()).baseName();
} else if (!project->title().isEmpty()) {
doc_name = project->title();
doc_name = QET::stringToFileName(doc_name);
if (!project->title().isEmpty()) {
doc_name = project->title();
} else if (!project->filePath().isEmpty()) {
doc_name = QFileInfo(project->filePath()).baseName();
}
doc_name = QET::stringToFileName(doc_name);
if (doc_name.isEmpty()) {
doc_name = tr("projet", "string used to generate a filename");
}
@@ -666,7 +666,7 @@ QList<Diagram *> ProjectPrintWindow::selectedDiagram() const
void ProjectPrintWindow::exportToPDF()
{
auto file_name = QFileDialog::getSaveFileName(this, tr("Exporter sous : "), m_printer->outputFileName(), tr("Fichier (*.pdf)"));
auto file_name = QFileDialog::getSaveFileName(this, tr("Exporter sous : "), m_printer->outputFileName(), tr("Fichier (*.pdf"));
if (file_name.isEmpty()) {
return;
}

View File

@@ -339,8 +339,11 @@ QString ProjectView::askUserForFilePath(bool assign) {
// if no filepath is provided, return an empty string
if (filepath.isEmpty()) return(filepath);
// // if the name does not end with the .qet extension, append it
// if (!filepath.endsWith(".qet", Qt::CaseInsensitive)) filepath += ".qet";
// if the name does not end with the .qet extension and we're _not_ using xdg-desktop-portal, append it
bool usesPortal =
qEnvironmentVariableIsSet("FLATPAK_ID") ||
qEnvironmentVariableIsSet("SNAP_NAME");
if (!filepath.endsWith(".qet", Qt::CaseInsensitive) && !usesPortal) filepath += ".qet";
if (assign) {
// assign the provided filepath to the currently edited project

View File

@@ -187,14 +187,13 @@ QHash<QString, XRefProperties> XRefProperties::defaultProperties()
}
bool XRefProperties::operator ==(const XRefProperties &xrp) const{
return (m_show_power_ctc == xrp.m_show_power_ctc
&& m_display == xrp.m_display
&& m_snap_to == xrp.m_snap_to
&& m_prefix == xrp.m_prefix
&& m_master_label== xrp.m_master_label
&& m_offset == xrp.m_offset
&& m_xref_pos == xrp.m_xref_pos
&& m_slave_label == xrp.m_slave_label);
return (m_show_power_ctc == xrp.m_show_power_ctc &&
m_display == xrp.m_display &&
m_snap_to == xrp.m_snap_to &&
m_prefix == xrp.m_prefix &&
m_master_label == xrp.m_master_label &&
m_offset == xrp.m_offset &&
m_xref_pos == xrp.m_xref_pos );
}
bool XRefProperties::operator !=(const XRefProperties &xrp) const

View File

@@ -1,77 +1,74 @@
/**
* pugixml parser - version 1.11
* --------------------------------------------------------
* Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
// #define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Tune this constant to adjust max nesting for XPath queries
// #define PUGIXML_XPATH_DEPTH_LIMIT 1024
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// Uncomment this to enable long long support
// #define PUGIXML_HAS_LONG_LONG
#endif
/**
* Copyright (c) 2006-2020 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* pugixml parser - version 1.10
* --------------------------------------------------------
* Copyright (C) 2006-2019, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to enable compact mode
// #define PUGIXML_COMPACT
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
// #define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// Uncomment this to enable long long support
// #define PUGIXML_HAS_LONG_LONG
#endif
/**
* Copyright (c) 2006-2019 Arseny Kapoulkine
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -29,9 +29,9 @@ class QActionGroup;
*/
namespace QET {
/// QElectroTech version (as string, used to mark projects and elements XML documents)
const QString version = "0.81";
const QString version = "0.80";
/// QElectroTech displayed version
const QString displayedVersion = "0.81";
const QString displayedVersion = "0.80";
QString license();
//Describe the current state of a graphic item

View File

@@ -35,7 +35,6 @@
#include "titleblocktemplate.h"
#include "ui/aboutqetdialog.h"
#include "ui/configpage/generalconfigurationpage.h"
#include "machine_info.h"
#include <cstdlib>
#include <iostream>
@@ -71,9 +70,6 @@ QString QETApp::m_user_custom_elements_dir = QString();
QString QETApp::m_user_custom_tbt_dir = QString();
QETApp *QETApp::m_qetapp = nullptr;
bool lang_is_set = false;
QString system_language = QString();
/**
@brief QETApp::QETApp
@@ -150,7 +146,6 @@ QETApp::~QETApp()
ElementFactory::dropInstance();
ElementPictureFactory::dropInstance();
MachineInfo::dropInstance();
}
@@ -230,16 +225,11 @@ void QETApp::setLanguage(const QString &desired_language) {
*/
QString QETApp::langFromSetting()
{
if (!lang_is_set)
{
QSettings settings;
system_language = settings.value("lang", "system").toString();
if(system_language == "system") {
system_language = QLocale::system().name().left(2);
}
lang_is_set = true;
QSettings settings;
QString system_language = settings.value("lang", "system").toString();
if(system_language == "system") {
system_language = QLocale::system().name().left(2);
}
return system_language;
}
/**

View File

@@ -84,7 +84,7 @@ class QetGraphicsHeaderItem : public QGraphicsObject
QRect m_current_rect;
QRectF m_bounding_rect;
QPointer<QAbstractItemModel> m_model;
QAbstractItemModel *m_model = nullptr;
QVector<int>
m_sections_minimum_width,

View File

@@ -156,17 +156,7 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) :
}
QetGraphicsTableItem::~QetGraphicsTableItem()
{
if (m_previous_table) {
if (m_next_table) {
m_previous_table->setNextTable(m_next_table);
} else {
m_previous_table->setNextTable(nullptr);
}
} else if (m_next_table) {
m_next_table->setPreviousTable(nullptr);
}
}
{}
/**
@brief QetGraphicsTableItem::setModel
@@ -185,7 +175,7 @@ void QetGraphicsTableItem::setModel(QAbstractItemModel *model)
this, &QetGraphicsTableItem::modelReseted);
}
m_model = model;
m_header_item->setModel(m_model);
m_header_item->setModel(model);
setUpColumnAndRowMinimumSize();
adjustSize();
@@ -210,7 +200,7 @@ void QetGraphicsTableItem::setModel(QAbstractItemModel *model)
*/
QAbstractItemModel *QetGraphicsTableItem::model() const
{
return m_model.data();
return m_model;
}
/**
@@ -280,8 +270,8 @@ void QetGraphicsTableItem::paint(
if (m_previous_table) //Remove the number of row already displayed by previous tables
row_count -= m_previous_table->displayNRowOffset();
if (m_number_of_row_to_display > 0) //User override the number of row to display
row_count = std::min(row_count, m_number_of_row_to_display);
if (m_number_of_displayed_row > 0) //User override the number of row to display
row_count = std::min(row_count, m_number_of_displayed_row);
//Draw horizontal lines
auto cell_height = static_cast<double>(m_current_size.height())/static_cast<double>(row_count);
@@ -374,8 +364,8 @@ QSize QetGraphicsTableItem::minimumSize() const
row_count -= m_previous_table->displayNRowOffset();
}
if (m_number_of_row_to_display > 0)
row_count = std::min(row_count, m_number_of_row_to_display);
if (m_number_of_displayed_row > 0)
row_count = std::min(row_count, m_number_of_displayed_row);
//m_minimum_column_width already take in count the minimum size of header
@@ -399,7 +389,7 @@ QSize QetGraphicsTableItem::minimumSize() const
*/
void QetGraphicsTableItem::setDisplayNRow(const int &number)
{
m_number_of_row_to_display = number;
m_number_of_displayed_row = number;
setToMinimumHeight();
if (m_next_table)
m_next_table->previousTableDisplayRowChanged();
@@ -412,7 +402,7 @@ void QetGraphicsTableItem::setDisplayNRow(const int &number)
*/
int QetGraphicsTableItem::displayNRow() const
{
return m_number_of_row_to_display;
return m_number_of_displayed_row;
}
/**
@@ -499,41 +489,19 @@ QString QetGraphicsTableItem::tableName() const
*/
int QetGraphicsTableItem::displayNRowOffset() const
{
auto offset_ = m_number_of_row_to_display;
auto offset_ = m_number_of_displayed_row;
if(m_previous_table)
offset_ += m_previous_table->displayNRowOffset();
return offset_;
}
/**
* @brief QetGraphicsTableItem::displayedRowCount
* @return the number of row displayed by this table
*/
int QetGraphicsTableItem::displayedRowCount() const
{
if (!m_model) {
return 0;
}
//Calcule the number of rows to display.
auto row_count = m_model->rowCount();
if (m_previous_table) //Remove the number of row already displayed by previous tables
row_count -= m_previous_table->displayNRowOffset();
if (m_number_of_row_to_display > 0) //User override the number of row to display
row_count = std::min(row_count, m_number_of_row_to_display);
return row_count;
}
QPointer<QetGraphicsTableItem> QetGraphicsTableItem::previousTable() const
QetGraphicsTableItem *QetGraphicsTableItem::previousTable() const
{
return m_previous_table;
}
QPointer<QetGraphicsTableItem> QetGraphicsTableItem::nextTable() const
QetGraphicsTableItem *QetGraphicsTableItem::nextTable() const
{
return m_next_table;
}
@@ -587,7 +555,7 @@ QDomElement QetGraphicsTableItem::toXml(QDomDocument &dom_document) const
dom_table.setAttribute("height", QString::number(m_current_size.height()));
dom_table.setAttribute("uuid", m_uuid.toString());
dom_table.setAttribute("name", m_name);
dom_table.setAttribute("display_n_row", QString::number(m_number_of_row_to_display));
dom_table.setAttribute("display_n_row", QString::number(m_number_of_displayed_row));
//Add the header xml
dom_table.appendChild(m_header_item->toXml(dom_document));
@@ -603,7 +571,7 @@ QDomElement QetGraphicsTableItem::toXml(QDomDocument &dom_document) const
{
//Add model
auto dom_model = dom_document.createElement("model");
auto project_db_model = static_cast<ProjectDBModel *>(m_model.data());
auto project_db_model = static_cast<ProjectDBModel *>(m_model);
dom_model.appendChild(project_db_model->toXml(dom_document));
dom_table.appendChild(dom_model);
@@ -645,7 +613,7 @@ void QetGraphicsTableItem::fromXml(const QDomElement &dom_element)
"uuid",
QUuid::createUuid().toString()));
m_name = dom_element.attribute("name");
m_number_of_row_to_display = dom_element.attribute(
m_number_of_displayed_row = dom_element.attribute(
"display_n_row",
QString::number(0)).toInt();
@@ -710,8 +678,8 @@ bool QetGraphicsTableItem::toDXF(const QString &filepath)
if (m_previous_table) //Remove the number of row already displayed by previous tables
row_count -= m_previous_table->displayNRowOffset();
if (m_number_of_row_to_display > 0) //User override the number of row to display
row_count = std::min(row_count, m_number_of_row_to_display);
if (m_number_of_displayed_row > 0) //User override the number of row to display
row_count = std::min(row_count, m_number_of_displayed_row);
//Draw horizontal lines
auto cell_height = static_cast<double>(m_current_size.height())/static_cast<double>(row_count);
@@ -838,18 +806,13 @@ QVariant QetGraphicsTableItem::itemChange(
return QetGraphicsItem::itemChange(change, value);
}
/**
* @brief QetGraphicsTableItem::modelReseted
*/
void QetGraphicsTableItem::modelReseted()
{
dataChanged(m_model->index(0,0), m_model->index(0,0), QVector<int>());
setToMinimumHeight();
if (!previousTable()) //this is the head table
{
if (!previousTable()) { //this is the head table
checkInsufficientRowsCount(this);
removeUselessNextTable();
}
}
@@ -1083,24 +1046,3 @@ void QetGraphicsTableItem::previousTableDisplayRowChanged()
m_next_table->previousTableDisplayRowChanged();
}
}
/**
* @brief QetGraphicsTableItem::removeUselessNextTable
* Remove next table if useless, an useless table with 0 row displayed.
* If \p recursive is true check and remove for all sub next table.
* @param recursive
*/
void QetGraphicsTableItem::removeUselessNextTable(bool recursive)
{
if (m_next_table)
{
if (recursive) {
m_next_table->removeUselessNextTable();
}
if (m_next_table->displayedRowCount() <= 0)
{
m_next_table.data()->deleteLater();
m_next_table.clear();
}
}
}

View File

@@ -79,9 +79,8 @@ class QetGraphicsTableItem : public QetGraphicsItem
void setTableName(const QString &name);
QString tableName() const;
int displayNRowOffset() const;
int displayedRowCount() const;
QPointer<QetGraphicsTableItem> previousTable() const;
QPointer<QetGraphicsTableItem> nextTable() const;
QetGraphicsTableItem *previousTable() const;
QetGraphicsTableItem *nextTable() const;
void setToMinimumHeight();
void initLink();
QUuid uuid() const {return m_uuid;}
@@ -121,14 +120,13 @@ class QetGraphicsTableItem : public QetGraphicsItem
void headerSectionResized();
void adjustSize();
void previousTableDisplayRowChanged();
void removeUselessNextTable(bool recursive = true);
QPointer<QAbstractItemModel> m_model;
QAbstractItemModel *m_model= nullptr;
QVector<int> m_minimum_column_width;
int
m_minimum_row_height,
m_number_of_row_to_display = 0,
m_number_of_displayed_row = 0,
m_br_margin = 10;
QSize
@@ -141,8 +139,9 @@ class QetGraphicsTableItem : public QetGraphicsItem
QetGraphicsHandlerItem m_handler_item;
QetGraphicsHeaderItem *m_header_item = nullptr;
QPointer<QetGraphicsTableItem> m_previous_table,
m_next_table;
QetGraphicsTableItem
*m_previous_table = nullptr,
*m_next_table = nullptr;
QString m_name;
QUuid

View File

@@ -128,15 +128,6 @@ void CrossRefItem::setUpConnection()
m_update_connection << connect(m_element,
&Element::linkedElementChanged,
this, &CrossRefItem::linkedChanged);
auto diagram_ = dynamic_cast<Diagram *>(this->scene());
auto formula_ = m_properties.masterLabel();
if (diagram_ &&
formula_.contains("%F"))
{
m_update_connection << connect(diagram_ , &Diagram::diagramInformationChanged,
this, &CrossRefItem::updateLabel);
}
linkedChanged();
updateLabel();
}
@@ -170,9 +161,13 @@ QPainterPath CrossRefItem::shape() const{
QString CrossRefItem::elementPositionText(
const Element *elmt, const bool &add_prefix) const
{
XRefProperties xrp =
m_element->diagram()->project()->defaultXRefProperties(
m_element->kindInformations()["type"].toString());
QString formula = xrp.masterLabel();
autonum::sequentialNumbers seq;
QString txt = autonum::AssignVariables::formulaToLabel(
m_properties.masterLabel(),
formula,
seq, elmt->diagram(),
elmt);

View File

@@ -1326,7 +1326,6 @@ void DynamicElementTextItem::updateXref()
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::xChanged, this, &DynamicElementTextItem::updateXref);
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::yChanged, this, &DynamicElementTextItem::updateXref);
m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::updateXref);
m_update_slave_Xref_connection << connect(diagram(), &Diagram::diagramInformationChanged, this, &DynamicElementTextItem::updateXref);
m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateXref);
m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::diagramRemoved, this, &DynamicElementTextItem::updateXref);
m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::XRefPropertiesChanged, this, &DynamicElementTextItem::updateXref);

View File

@@ -736,38 +736,48 @@ bool Element::fromXml(
}
QHash<int, Terminal *> priv_id_adr;
for (auto *qgi : childItems())
{
if (auto terminal_ = qgraphicsitem_cast<Terminal *>(qgi))
{
for(auto qde : liste_terminals)
{
if (terminal_ -> fromXml(qde))
{
priv_id_adr.insert(qde.attribute(QStringLiteral("id")).toInt(),
terminal_);
int terminals_non_trouvees = 0;
foreach(QGraphicsItem *qgi, childItems()) {
if (Terminal *p = qgraphicsitem_cast<Terminal *>(qgi)) {
bool terminal_trouvee = false;
foreach(QDomElement qde, liste_terminals) {
if (p -> fromXml(qde)) {
priv_id_adr.insert(
qde.attribute(
"id").toInt(),
p);
terminal_trouvee = true;
// We used to break here, because we did not expect
// several terminals to share the same position.
// Of course, it finally happened.
}
}
if (!terminal_trouvee) ++ terminals_non_trouvees;
}
}
//Check that associated id/adress doesn't conflict with table_id_adr
for(auto found_id : priv_id_adr.keys())
if (terminals_non_trouvees > 0)
{
if (table_id_adr.contains(found_id))
{
//This element got an id who is already referenced (= conflict)
m_state = QET::GIOK;
return(false);
}
m_state = QET::GIOK;
return(false);
}
//Copie the association id/adress
for(auto found_id : priv_id_adr.keys()) {
table_id_adr.insert(found_id,
priv_id_adr.value(found_id));
else
{
// verifie que les associations id / adr n'entrent pas en conflit avec table_id_adr
foreach(int id_trouve, priv_id_adr.keys())
{
if (table_id_adr.contains(id_trouve))
{
// cet element possede un id qui est deja reference (= conflit)
m_state = QET::GIOK;
return(false);
}
}
// copie des associations id / adr
foreach(int id_trouve, priv_id_adr.keys()) {
table_id_adr.insert(id_trouve,
priv_id_adr.value(id_trouve));
}
}
//load uuid of connected elements

View File

@@ -120,19 +120,8 @@ QETProject::QETProject(KAutoSaveFile *backup, QObject *parent) :
*/
QETProject::~QETProject()
{
//Each time a diagram is deleted we also remove it from m_diagram_list
//because a lot of thing append during the destructor of a diagram class
//and one of these thing (not directly in the destructor of the diagram
//but in another destructor called by the diagram destructor)
//is to get the diagram list of the project to make some updates @see QList<Diagram *> QETProject::diagrams() const.
//So we need to remove the freshly deleted diagram from the list
//in each iteration of the loop to avoid the use of a dangling pointer.
const auto diag_list = m_diagrams_list;
for (const auto &diagram : diag_list)
{
for (auto diagram : m_diagrams_list)
delete diagram;
m_diagrams_list.removeOne(diagram);
}
}
/**
@@ -170,7 +159,7 @@ void QETProject::init()
writeBackup();
QSettings settings;
int autosave_interval = settings.value(QStringLiteral("diagrameditor/autosave-interval"), 0).toInt();
int autosave_interval = settings.value("diagrameditor/autosave-interval", 0).toInt();
if(autosave_interval > 0)
{
int ms = autosave_interval*60*1000;
@@ -1291,13 +1280,13 @@ void QETProject::readProjectXml(QDomDocument &xml_project)
m_state = ProjectParsingRunning;
//The roots of the xml document must be a "project" element
if (root_elmt.tagName() == QLatin1String("project"))
if (root_elmt.tagName() == "project")
{
//Normal opening mode
if (root_elmt.hasAttribute(QStringLiteral("version")))
if (root_elmt.hasAttribute("version"))
{
bool conv_ok;
m_project_qet_version = root_elmt.attribute(QStringLiteral("version")).toDouble(&conv_ok);
m_project_qet_version = root_elmt.attribute("version").toDouble(&conv_ok);
#if TODO_LIST
#pragma message("@TODO use of version convert")
#endif
@@ -1323,7 +1312,7 @@ void QETProject::readProjectXml(QDomDocument &xml_project)
}
}
}
setTitle(root_elmt.attribute(QStringLiteral("title")));
setTitle(root_elmt.attribute("title"));
}
else
{
@@ -1373,7 +1362,7 @@ void QETProject::readDiagramsXml(QDomDocument &xml_project)
}
//Search the diagrams in the project
QDomNodeList diagram_nodes = xml_project.elementsByTagName(QStringLiteral("diagram"));
QDomNodeList diagram_nodes = xml_project.elementsByTagName("diagram");
if(dlgWaiting)
dlgWaiting->setProgressBarRange(0, diagram_nodes.length()*3);
@@ -1392,7 +1381,7 @@ void QETProject::readDiagramsXml(QDomDocument &xml_project)
int diagram_order = -1;
if (!QET::attributeIsAnInteger(diagram_xml_element,
QStringLiteral("order"),
"order",
&diagram_order))
diagram_order = 500000;
@@ -1435,7 +1424,7 @@ void QETProject::readDiagramsXml(QDomDocument &xml_project)
void QETProject::readElementsCollectionXml(QDomDocument &xml_project)
{
//Get the embedded elements collection of the project
QDomNodeList collection_roots = xml_project.elementsByTagName(QStringLiteral("collection"));
QDomNodeList collection_roots = xml_project.elementsByTagName("collection");
QDomElement collection_root;
if (!collection_roots.isEmpty())
@@ -1460,8 +1449,8 @@ void QETProject::readElementsCollectionXml(QDomDocument &xml_project)
*/
void QETProject::readProjectPropertiesXml(QDomDocument &xml_project)
{
for (auto dom_elmt : QET::findInDomElement(xml_project.documentElement(), QStringLiteral("properties")))
m_project_properties.fromXml(dom_elmt);
foreach (QDomElement e, QET::findInDomElement(xml_project.documentElement(), "properties"))
m_project_properties.fromXml(e);
}
/**
@@ -1473,7 +1462,7 @@ void QETProject::readProjectPropertiesXml(QDomDocument &xml_project)
void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project)
{
// Find xml element where is stored properties for new diagram
QDomNodeList newdiagrams_nodes = xml_project.elementsByTagName(QStringLiteral("newdiagrams"));
QDomNodeList newdiagrams_nodes = xml_project.elementsByTagName("newdiagrams");
if (newdiagrams_nodes.isEmpty()) return;
QDomElement newdiagrams_elmt = newdiagrams_nodes.at(0).toElement();
@@ -1493,21 +1482,21 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project)
QDomElement child_elmt = child.toElement();
if (child_elmt.isNull()) continue;
if (child_elmt.tagName() == QLatin1String("border"))
if (child_elmt.tagName() == "border")
border_elmt = child_elmt;
else if (child_elmt.tagName() == QLatin1String("inset"))
else if (child_elmt.tagName() == "inset")
titleblock_elmt = child_elmt;
else if (child_elmt.tagName() == QLatin1String("conductors"))
else if (child_elmt.tagName() == "conductors")
conductors_elmt = child_elmt;
else if (child_elmt.tagName() == QLatin1String("report"))
else if (child_elmt.tagName() == "report")
report_elmt = child_elmt;
else if (child_elmt.tagName() == QLatin1String("xrefs"))
else if (child_elmt.tagName() == "xrefs")
xref_elmt = child_elmt;
else if (child_elmt.tagName() == QLatin1String("conductors_autonums"))
else if (child_elmt.tagName() == "conductors_autonums")
conds_autonums = child_elmt;
else if (child_elmt.tagName()== QLatin1String("folio_autonums"))
else if (child_elmt.tagName()== "folio_autonums")
folio_autonums = child_elmt;
else if (child_elmt.tagName()== QLatin1String("element_autonums"))
else if (child_elmt.tagName()== "element_autonums")
element_autonums = child_elmt;
}
@@ -1515,21 +1504,21 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project)
if (!border_elmt.isNull()) default_border_properties_.fromXml(border_elmt);
if (!titleblock_elmt.isNull()) default_titleblock_properties_.fromXml(titleblock_elmt);
if (!conductors_elmt.isNull()) default_conductor_properties_.fromXml(conductors_elmt);
if (!report_elmt.isNull()) setDefaultReportProperties(report_elmt.attribute(QStringLiteral("label")));
if (!report_elmt.isNull()) setDefaultReportProperties(report_elmt.attribute("label"));
if (!xref_elmt.isNull())
{
for (auto elmt : QET::findInDomElement(xref_elmt, QStringLiteral("xref")))
foreach(QDomElement elmt, QET::findInDomElement(xref_elmt, "xref"))
{
XRefProperties xrp;
xrp.fromXml(elmt);
m_default_xref_properties.insert(elmt.attribute(QStringLiteral("type")), xrp);
m_default_xref_properties.insert(elmt.attribute("type"), xrp);
}
}
if (!conds_autonums.isNull())
{
m_current_conductor_autonum = conds_autonums.attribute(QStringLiteral("current_autonum"));
m_freeze_new_conductors = conds_autonums.attribute(QStringLiteral("freeze_new_conductors")) == QLatin1String("true");
for (auto elmt : QET::findInDomElement(conds_autonums, QStringLiteral("conductor_autonum")))
m_current_conductor_autonum = conds_autonums.attribute("current_autonum");
m_freeze_new_conductors = conds_autonums.attribute("freeze_new_conductors") == "true";
foreach (QDomElement elmt, QET::findInDomElement(conds_autonums, "conductor_autonum"))
{
NumerotationContext nc;
nc.fromXml(elmt);
@@ -1538,22 +1527,22 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project)
}
if (!folio_autonums.isNull())
{
for (auto elmt : QET::findInDomElement(folio_autonums, QStringLiteral("folio_autonum")))
foreach (QDomElement elmt, QET::findInDomElement(folio_autonums, "folio_autonum"))
{
NumerotationContext nc;
nc.fromXml(elmt);
m_folio_autonum.insert(elmt.attribute(QStringLiteral("title")), nc);
m_folio_autonum.insert(elmt.attribute("title"), nc);
}
}
if (!element_autonums.isNull())
{
m_current_element_autonum = element_autonums.attribute(QStringLiteral("current_autonum"));
m_freeze_new_elements = element_autonums.attribute(QStringLiteral("freeze_new_elements")) == QLatin1String("true");
for (auto elmt : QET::findInDomElement(element_autonums, QStringLiteral("element_autonum")))
m_current_element_autonum = element_autonums.attribute("current_autonum");
m_freeze_new_elements = element_autonums.attribute("freeze_new_elements") == "true";
foreach (QDomElement elmt, QET::findInDomElement(element_autonums, "element_autonum"))
{
NumerotationContext nc;
nc.fromXml(elmt);
m_element_autonum.insert(elmt.attribute(QStringLiteral("title")), nc);
m_element_autonum.insert(elmt.attribute("title"), nc);
}
}
}

View File

@@ -152,7 +152,8 @@ void AboutQETDialog::setVersion()
QString str = "<span style=\"font-weight:bold;font-size:16pt;\">QElectroTech V "
+ QET::displayedVersion
+ "</span>";
ui->m_version_label->setText(str + MachineInfo::instance()->compilation_info());
Machine_info *my_ma =new Machine_info(this);
ui->m_version_label->setText(str + my_ma->compilation_info());
}
/**

View File

@@ -98,14 +98,6 @@
</item>
</layout>
</widget>
<tabstops>
<tabstop>m_colums_count_sp</tabstop>
<tabstop>m_columns_width_sp</tabstop>
<tabstop>m_rows_count_sp</tabstop>
<tabstop>m_rows_height_sp</tabstop>
<tabstop>m_display_columns_cb</tabstop>
<tabstop>m_display_rows_cb</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>666</width>
<width>662</width>
<height>418</height>
</rect>
</property>
@@ -581,41 +581,6 @@
<header>kcolorbutton.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>tabWidget_2</tabstop>
<tabstop>m_multiwires_gb</tabstop>
<tabstop>m_one_text_per_folio_cb</tabstop>
<tabstop>m_text_size_sb</tabstop>
<tabstop>m_formula_le</tabstop>
<tabstop>m_text_le</tabstop>
<tabstop>m_show_text_cb</tabstop>
<tabstop>m_text_color_kpb</tabstop>
<tabstop>m_available_autonum_cb</tabstop>
<tabstop>m_edit_autonum_pb</tabstop>
<tabstop>m_function_le</tabstop>
<tabstop>m_tension_protocol_le</tabstop>
<tabstop>m_wire_color_le</tabstop>
<tabstop>m_wire_section_le</tabstop>
<tabstop>m_cable_le</tabstop>
<tabstop>m_bus_le</tabstop>
<tabstop>m_verti_cb</tabstop>
<tabstop>m_horiz_cb</tabstop>
<tabstop>m_singlewire_gb</tabstop>
<tabstop>m_phase_sb</tabstop>
<tabstop>m_update_preview_pb</tabstop>
<tabstop>m_neutral_cb</tabstop>
<tabstop>m_earth_cb</tabstop>
<tabstop>m_phase_cb</tabstop>
<tabstop>m_phase_slider</tabstop>
<tabstop>m_pen_cb</tabstop>
<tabstop>m_color_kpb</tabstop>
<tabstop>m_color_2_gb</tabstop>
<tabstop>m_dash_size_sb</tabstop>
<tabstop>m_color_2_kpb</tabstop>
<tabstop>m_cond_size_sb</tabstop>
<tabstop>m_line_style_cb</tabstop>
</tabstops>
<resources>
<include location="../../qelectrotech.qrc"/>
</resources>

View File

@@ -17,7 +17,7 @@
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>5</number>
<number>0</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">
@@ -811,35 +811,19 @@ Vous pouvez spécifier ici la valeur par défaut de ce champ pour les éléments
</layout>
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>m_use_system_color_cb</tabstop>
<tabstop>m_use_gesture_trackpad</tabstop>
<tabstop>m_zoom_out_beyond_folio</tabstop>
<tabstop>m_use_windows_mode_rb</tabstop>
<tabstop>m_use_tab_mode_rb</tabstop>
<tabstop>m_save_label_paste</tabstop>
<tabstop>m_use_folio_label</tabstop>
<tabstop>m_export_terminal</tabstop>
<tabstop>m_border_0</tabstop>
<tabstop>m_autosave_sb</tabstop>
<tabstop>m_use_gesture_trackpad</tabstop>
<tabstop>m_zoom_out_beyond_folio</tabstop>
<tabstop>m_common_elmt_path_cb</tabstop>
<tabstop>m_custom_elmt_path_cb</tabstop>
<tabstop>m_custom_tbt_path_cb</tabstop>
<tabstop>m_highlight_integrated_elements</tabstop>
<tabstop>m_default_elements_info</tabstop>
<tabstop>m_lang_cb</tabstop>
<tabstop>m_dyn_text_font_pb</tabstop>
<tabstop>m_dyn_text_rotation_sb</tabstop>
<tabstop>m_dyn_text_width_sb</tabstop>
<tabstop>m_indi_text_font_pb</tabstop>
<tabstop>m_indi_text_rotation_sb</tabstop>
<tabstop>m_font_pb</tabstop>
<tabstop>DiagramEditor_xGrid_sb</tabstop>
<tabstop>DiagramEditor_yGrid_sb</tabstop>
<tabstop>DiagramEditor_xKeyGrid_sb</tabstop>
<tabstop>DiagramEditor_yKeyGrid_sb</tabstop>
<tabstop>DiagramEditor_xKeyGridFine_sb</tabstop>
<tabstop>DiagramEditor_yKeyGridFine_sb</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@@ -29,7 +29,7 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../qelectrotech.qrc">
<iconset>
<normaloff>:/ico/16x16/folder-open.png</normaloff>:/ico/16x16/folder-open.png</iconset>
</property>
</widget>
@@ -40,21 +40,13 @@
<string/>
</property>
<property name="icon">
<iconset resource="../../qelectrotech.qrc">
<iconset>
<normaloff>:/ico/16x16/document-save.png</normaloff>:/ico/16x16/document-save.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>m_combo_box</tabstop>
<tabstop>m_load_pb</tabstop>
<tabstop>m_line_edit</tabstop>
<tabstop>m_save_pb</tabstop>
</tabstops>
<resources>
<include location="../../qelectrotech.qrc"/>
</resources>
<resources/>
<connections/>
</ui>

View File

@@ -163,16 +163,6 @@ Veuillez utiliser l'éditeur avancé pour cela.</string>
</item>
</layout>
</widget>
<tabstops>
<tabstop>m_line_edit</tabstop>
<tabstop>m_font_pb</tabstop>
<tabstop>m_advanced_editor_pb</tabstop>
<tabstop>m_x_sb</tabstop>
<tabstop>m_y_sb</tabstop>
<tabstop>m_angle_sb</tabstop>
<tabstop>m_size_sb</tabstop>
<tabstop>m_break_html_pb</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -256,15 +256,6 @@
<header>kcolorbutton.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_style_cb</tabstop>
<tabstop>m_size_dsb</tabstop>
<tabstop>m_color_kpb</tabstop>
<tabstop>m_brush_style_cb</tabstop>
<tabstop>m_brush_color_kpb</tabstop>
<tabstop>m_lock_pos_cb</tabstop>
<tabstop>m_close_polygon</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -2,14 +2,6 @@
<ui version="4.0">
<class>XRefPropertiesWidget</class>
<widget class="QWidget" name="XRefPropertiesWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>376</width>
<height>531</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
@@ -273,20 +265,6 @@
</item>
</layout>
</widget>
<tabstops>
<tabstop>m_type_cb</tabstop>
<tabstop>m_snap_to_cb</tabstop>
<tabstop>m_offset_sb</tabstop>
<tabstop>m_xrefpos_cb</tabstop>
<tabstop>m_display_has_contacts_rb</tabstop>
<tabstop>m_display_has_cross_rb</tabstop>
<tabstop>m_master_le</tabstop>
<tabstop>m_slave_le</tabstop>
<tabstop>m_show_power_cb</tabstop>
<tabstop>m_power_prefix_le</tabstop>
<tabstop>m_delay_prefix_le</tabstop>
<tabstop>m_switch_prefix_le</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>