aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp')
-rw-r--r--src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp b/src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp
new file mode 100644
index 0000000000..21de2a7919
--- /dev/null
+++ b/src/libs/qmlpuppetcommunication/commands/valueschangedcommand.cpp
@@ -0,0 +1,181 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0
+
+#include "valueschangedcommand.h"
+
+#include "sharedmemory.h"
+
+#include <QCache>
+#include <QDebug>
+#include <QIODevice>
+
+#include <cstring>
+
+#include <algorithm>
+
+namespace QmlDesigner {
+
+// using cache as a container which deletes sharedmemory pointers at process exit
+using GlobalSharedMemoryContainer = QCache<qint32, SharedMemory>;
+Q_GLOBAL_STATIC_WITH_ARGS(GlobalSharedMemoryContainer, globalSharedMemoryContainer, (10000))
+
+ValuesChangedCommand::ValuesChangedCommand()
+ : m_keyNumber(0)
+{
+}
+
+ValuesChangedCommand::ValuesChangedCommand(const QVector<PropertyValueContainer> &valueChangeVector)
+ : m_valueChangeVector (valueChangeVector),
+ m_keyNumber(0)
+{
+}
+
+const QVector<PropertyValueContainer> ValuesChangedCommand::valueChanges() const
+{
+ return m_valueChangeVector;
+}
+
+quint32 ValuesChangedCommand::keyNumber() const
+{
+ return m_keyNumber;
+}
+
+void ValuesChangedCommand::removeSharedMemorys(const QVector<qint32> &keyNumberVector)
+{
+ for (qint32 keyNumber : keyNumberVector) {
+ SharedMemory *sharedMemory = globalSharedMemoryContainer()->take(keyNumber);
+ delete sharedMemory;
+ }
+}
+
+void ValuesChangedCommand::sort()
+{
+ std::sort(m_valueChangeVector.begin(), m_valueChangeVector.end());
+}
+
+static const QLatin1String valueKeyTemplateString("Values-%1");
+
+static SharedMemory *createSharedMemory(qint32 key, int byteCount)
+{
+ SharedMemory *sharedMemory = new SharedMemory(QString(valueKeyTemplateString).arg(key));
+
+ bool sharedMemoryIsCreated = sharedMemory->create(byteCount);
+
+ if (sharedMemoryIsCreated) {
+ globalSharedMemoryContainer()->insert(key, sharedMemory);
+ return sharedMemory;
+ } else {
+ delete sharedMemory;
+ }
+
+ return nullptr;
+}
+
+QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command)
+{
+ static const bool dontUseSharedMemory = qEnvironmentVariableIsSet("DESIGNER_DONT_USE_SHARED_MEMORY");
+
+ QVector<PropertyValueContainer> propertyValueContainer = command.valueChanges();
+
+ if (command.transactionOption != ValuesChangedCommand::TransactionOption::None) {
+ PropertyValueContainer optionContainer(command.transactionOption);
+ propertyValueContainer.append(optionContainer);
+ }
+
+ if (!dontUseSharedMemory && propertyValueContainer.count() > 5) {
+ static quint32 keyCounter = 0;
+ ++keyCounter;
+ command.m_keyNumber = keyCounter;
+ QByteArray outDataStreamByteArray;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ QDataStream temporaryOutDataStream(&outDataStreamByteArray, QIODevice::WriteOnly);
+#else
+ QDataStream temporaryOutDataStream(&outDataStreamByteArray, QDataStream::WriteOnly);
+#endif
+ temporaryOutDataStream.setVersion(QDataStream::Qt_4_8);
+
+ temporaryOutDataStream << propertyValueContainer;
+
+ SharedMemory *sharedMemory = createSharedMemory(keyCounter, outDataStreamByteArray.size());
+
+ if (sharedMemory) {
+ sharedMemory->lock();
+ std::memcpy(sharedMemory->data(), outDataStreamByteArray.constData(), sharedMemory->size());
+ sharedMemory->unlock();
+
+ out << command.keyNumber();
+ return out;
+ }
+ }
+
+ out << qint32(0);
+ out << propertyValueContainer;
+
+ return out;
+}
+
+void readSharedMemory(qint32 key, QVector<PropertyValueContainer> *valueChangeVector)
+{
+ SharedMemory sharedMemory(QString(valueKeyTemplateString).arg(key));
+ bool canAttach = sharedMemory.attach(QSharedMemory::ReadOnly);
+
+ if (canAttach) {
+ sharedMemory.lock();
+
+ QDataStream in(QByteArray::fromRawData(static_cast<const char*>(sharedMemory.constData()), sharedMemory.size()));
+ in.setVersion(QDataStream::Qt_4_8);
+ in >> *valueChangeVector;
+
+ sharedMemory.unlock();
+ sharedMemory.detach();
+ }
+}
+
+QDataStream &operator>>(QDataStream &in, ValuesChangedCommand &command)
+{
+ in >> command.m_keyNumber;
+
+ QVector<PropertyValueContainer> valueChangeVector;
+
+ if (command.keyNumber() > 0)
+ readSharedMemory(command.keyNumber(), &valueChangeVector);
+ else
+ in >> valueChangeVector;
+
+ // '-option-' is not a valid property name and indicates that we store the transaction option.
+ if (!valueChangeVector.isEmpty() && valueChangeVector.last().name() == "-option-") {
+ command.transactionOption =
+ static_cast<ValuesChangedCommand::TransactionOption>(valueChangeVector.last().instanceId());
+ valueChangeVector.removeLast();
+ }
+
+ command.m_valueChangeVector = valueChangeVector;
+
+ return in;
+}
+
+bool operator ==(const ValuesChangedCommand &first, const ValuesChangedCommand &second)
+{
+ return first.m_valueChangeVector == second.m_valueChangeVector
+ && first.transactionOption == second.transactionOption;
+}
+
+QDebug operator <<(QDebug debug, const ValuesChangedCommand &command)
+{
+ return debug.nospace() << "ValuesChangedCommand("
+ << "keyNumber: " << command.keyNumber() << ", "
+ << command.valueChanges() << ")";
+}
+
+QDataStream &operator<<(QDataStream &out, const ValuesModifiedCommand &command)
+{
+ return out << static_cast<const ValuesChangedCommand &>(command);
+}
+
+QDataStream &operator>>(QDataStream &in, ValuesModifiedCommand &command)
+{
+ return in >> static_cast<ValuesChangedCommand &>(command);
+}
+
+
+} // namespace QmlDesigner