/**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://www.qt.io/licensing. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "valueschangedcommand.h" #include "sharedmemory.h" #include #include #include namespace QmlDesigner { // using cache as a container which deletes sharedmemory pointers at process exit typedef QCache GlobalSharedMemoryContainer; Q_GLOBAL_STATIC_WITH_ARGS(GlobalSharedMemoryContainer, globalSharedMemoryContainer, (10000)) ValuesChangedCommand::ValuesChangedCommand() : m_keyNumber(0) { } ValuesChangedCommand::ValuesChangedCommand(const QVector &valueChangeVector) : m_valueChangeVector (valueChangeVector), m_keyNumber(0) { } QVector ValuesChangedCommand::valueChanges() const { return m_valueChangeVector; } quint32 ValuesChangedCommand::keyNumber() const { return m_keyNumber; } void ValuesChangedCommand::removeSharedMemorys(const QVector &keyNumberVector) { foreach (qint32 keyNumber, keyNumberVector) { SharedMemory *sharedMemory = globalSharedMemoryContainer()->take(keyNumber); delete sharedMemory; } } void ValuesChangedCommand::sort() { qSort(m_valueChangeVector); } 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 0; } QDataStream &operator<<(QDataStream &out, const ValuesChangedCommand &command) { static const bool dontUseSharedMemory = !qgetenv("DESIGNER_DONT_USE_SHARED_MEMORY").isEmpty(); if (!dontUseSharedMemory && command.valueChanges().count() > 5) { static quint32 keyCounter = 0; ++keyCounter; command.m_keyNumber = keyCounter; QByteArray outDataStreamByteArray; QDataStream temporaryOutDataStream(&outDataStreamByteArray, QIODevice::WriteOnly); temporaryOutDataStream.setVersion(QDataStream::Qt_4_8); temporaryOutDataStream << command.valueChanges(); 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 << command.valueChanges(); return out; } void readSharedMemory(qint32 key, QVector *valueChangeVector) { SharedMemory sharedMemory(QString(valueKeyTemplateString).arg(key)); bool canAttach = sharedMemory.attach(QSharedMemory::ReadOnly); if (canAttach) { sharedMemory.lock(); QDataStream in(QByteArray::fromRawData(static_cast(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; if (command.keyNumber() > 0) { readSharedMemory(command.keyNumber(), &command.m_valueChangeVector); } else { in >> command.m_valueChangeVector; } return in; } bool operator ==(const ValuesChangedCommand &first, const ValuesChangedCommand &second) { return first.m_valueChangeVector == second.m_valueChangeVector; } QDebug operator <<(QDebug debug, const ValuesChangedCommand &command) { return debug.nospace() << "ValuesChangedCommand(" << "keyNumber: " << command.keyNumber() << ", " << command.valueChanges() << ")"; } } // namespace QmlDesigner