nodeinstanceserverproxy.cpp 22 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** 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://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: 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
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29

30 31 32 33 34 35 36
#include "nodeinstanceserverproxy.h"

#include <QLocalServer>
#include <QLocalSocket>
#include <QProcess>
#include <QCoreApplication>
#include <QUuid>
37
#include <QFileInfo>
38
#include <QDir>
39
#include <QTimer>
40
#include <QTextStream>
41 42 43 44 45

#include "createinstancescommand.h"
#include "createscenecommand.h"
#include "changevaluescommand.h"
#include "changebindingscommand.h"
46
#include "changeauxiliarycommand.h"
47 48 49 50 51 52 53
#include "changefileurlcommand.h"
#include "removeinstancescommand.h"
#include "clearscenecommand.h"
#include "removepropertiescommand.h"
#include "reparentinstancescommand.h"
#include "changeidscommand.h"
#include "changestatecommand.h"
54
#include "completecomponentcommand.h"
55
#include "changenodesourcecommand.h"
56 57 58 59

#include "informationchangedcommand.h"
#include "pixmapchangedcommand.h"
#include "valueschangedcommand.h"
60
#include "childrenchangedcommand.h"
61
#include "statepreviewimagechangedcommand.h"
62
#include "componentcompletedcommand.h"
63
#include "tokencommand.h"
64
#include "removesharedmemorycommand.h"
65
#include "endpuppetcommand.h"
66
#include "synchronizecommand.h"
Marco Bubke's avatar
Marco Bubke committed
67
#include "debugoutputcommand.h"
68

69
#include "nodeinstanceview.h"
70 71

#include "import.h"
72 73 74

#include <utils/hostosinfo.h>

75 76
#include <QMessageBox>

77
namespace {
78
#ifdef Q_OS_MAC
79
#  define SHARE_PATH "/../Resources"
80
#else
81
#  define SHARE_PATH "/../share/qtcreator"
82 83 84 85 86 87 88 89 90 91 92 93 94 95
#endif

static QString applicationDirPath()
{
    return QCoreApplication::applicationDirPath();
}

static inline QString sharedDirPath()
{
    QString appPath = applicationDirPath();

    return QFileInfo(appPath + SHARE_PATH).absoluteFilePath();
}

96 97
static QLatin1String qmlPuppetApplicationDirectoryForTests()
{
98 99 100
    if (Utils::HostOsInfo::isWindowsHost())
        //one more - debug/release dir
        return QLatin1String("/../../../../../../bin/");
101 102 103
    return QLatin1String("/../../../../../bin/");
}
} //namespace
104 105 106

namespace QmlDesigner {

107
static bool hasQtQuick2(NodeInstanceView *nodeInstanceView)
108 109 110
{
    if (nodeInstanceView && nodeInstanceView->model()) {
        foreach (const Import &import ,nodeInstanceView->model()->imports()) {
111
            if (import.url() ==  "QtQuick" && import.version().toDouble() >= 2.0)
112 113 114 115 116 117 118
                return true;
        }
    }

    return false;
}

119
NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView, RunModus runModus, const QString &pathToQt)
120 121 122
    : NodeInstanceServerInterface(nodeInstanceView),
      m_localServer(new QLocalServer(this)),
      m_nodeInstanceView(nodeInstanceView),
123
      m_firstBlockSize(0),
124
      m_secondBlockSize(0),
125
      m_thirdBlockSize(0),
126 127 128 129
      m_writeCommandCounter(0),
      m_firstLastReadCommandCounter(0),
      m_secondLastReadCommandCounter(0),
      m_thirdLastReadCommandCounter(0),
130 131
      m_runModus(runModus),
      m_synchronizeId(-1)
132
{
133
   Q_UNUSED(pathToQt);
134 135 136
   QString socketToken(QUuid::createUuid().toString());

   m_localServer->listen(socketToken);
137
   m_localServer->setMaxPendingConnections(3);
138

139 140
   QString applicationPath =  pathToQt + QLatin1String("/bin");
   if (runModus == TestModus) {
141
       applicationPath = QCoreApplication::applicationDirPath()
142 143
           + qmlPuppetApplicationDirectoryForTests()
           + qmlPuppetApplicationName();
144
   } else {
145
       applicationPath = macOSBundlePath(applicationPath);
Robert Loehning's avatar
Robert Loehning committed
146
       applicationPath += QLatin1Char('/') + qmlPuppetApplicationName();
147 148 149 150
       if (!QFileInfo(applicationPath).exists()) { //No qmlpuppet in Qt
           //We have to find out how to give not too intrusive feedback
           applicationPath =  QCoreApplication::applicationDirPath();
           applicationPath = macOSBundlePath(applicationPath);
Robert Loehning's avatar
Robert Loehning committed
151
           applicationPath += QLatin1Char('/') + qmlPuppetApplicationName();
152
       }
153
   }
154

155
   QByteArray envImportPath = qgetenv("QTCREATOR_QMLPUPPET_PATH");
156
   if (!envImportPath.isEmpty())
157 158
       applicationPath = envImportPath;

159
   QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
160

161 162 163 164
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) && (defined(Q_OS_MAC) || defined(Q_OS_LINUX))
   enviroment.insert(QLatin1String("DESIGNER_DONT_USE_SHARED_MEMORY"), QLatin1String("1"));
#endif

165 166
   if (QFileInfo(applicationPath).exists()) {
       m_qmlPuppetEditorProcess = new QProcess;
167
       m_qmlPuppetEditorProcess->setProcessEnvironment(environment);
168
       m_qmlPuppetEditorProcess->setObjectName("EditorProcess");
169 170 171
       connect(m_qmlPuppetEditorProcess.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
       connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), m_qmlPuppetEditorProcess.data(), SLOT(kill()));
       bool fowardQmlpuppetOutput = !qgetenv("FORWARD_QMLPUPPET_OUTPUT").isEmpty();
172
       if (fowardQmlpuppetOutput)
173 174
           m_qmlPuppetEditorProcess->setProcessChannelMode(QProcess::ForwardedChannels);
       m_qmlPuppetEditorProcess->start(applicationPath, QStringList() << socketToken << "editormode" << "-graphicssystem raster");
175

176 177
       if (runModus == NormalModus) {
           m_qmlPuppetPreviewProcess = new QProcess;
178
           m_qmlPuppetPreviewProcess->setProcessEnvironment(environment);
179
           m_qmlPuppetPreviewProcess->setObjectName("PreviewProcess");
180 181 182 183 184
           connect(m_qmlPuppetPreviewProcess.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
           connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), m_qmlPuppetPreviewProcess.data(), SLOT(kill()));
           if (fowardQmlpuppetOutput)
               m_qmlPuppetPreviewProcess->setProcessChannelMode(QProcess::ForwardedChannels);
           m_qmlPuppetPreviewProcess->start(applicationPath, QStringList() << socketToken << "previewmode" << "-graphicssystem raster");
185

186
           m_qmlPuppetRenderProcess = new QProcess;
187
           m_qmlPuppetRenderProcess->setProcessEnvironment(environment);
188
           m_qmlPuppetRenderProcess->setObjectName("RenderProcess");
189 190 191 192 193
           connect(m_qmlPuppetRenderProcess.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
           connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), m_qmlPuppetRenderProcess.data(), SLOT(kill()));
           if (fowardQmlpuppetOutput)
               m_qmlPuppetRenderProcess->setProcessChannelMode(QProcess::ForwardedChannels);
           m_qmlPuppetRenderProcess->start(applicationPath, QStringList() << socketToken << "rendermode" << "-graphicssystem raster");
194

195
       }
196

197
       connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
198

199 200
       if (m_qmlPuppetEditorProcess->waitForStarted(10000)) {
           connect(m_qmlPuppetEditorProcess.data(), SIGNAL(finished(int)), m_qmlPuppetEditorProcess.data(),SLOT(deleteLater()));
201

202 203 204
           if (runModus == NormalModus) {
               m_qmlPuppetPreviewProcess->waitForStarted();
               connect(m_qmlPuppetPreviewProcess.data(), SIGNAL(finished(int)), m_qmlPuppetPreviewProcess.data(),SLOT(deleteLater()));
205

206 207 208
               m_qmlPuppetRenderProcess->waitForStarted();
               connect(m_qmlPuppetRenderProcess.data(), SIGNAL(finished(int)), m_qmlPuppetRenderProcess.data(),SLOT(deleteLater()));
           }
209

210 211
           if (!m_localServer->hasPendingConnections())
               m_localServer->waitForNewConnection(10000);
212

213 214
           m_firstSocket = m_localServer->nextPendingConnection();
           connect(m_firstSocket.data(), SIGNAL(readyRead()), this, SLOT(readFirstDataStream()));
215

216 217 218
           if (runModus == NormalModus) {
               if (!m_localServer->hasPendingConnections())
                   m_localServer->waitForNewConnection(10000);
219

220 221
               m_secondSocket = m_localServer->nextPendingConnection();
               connect(m_secondSocket.data(), SIGNAL(readyRead()), this, SLOT(readSecondDataStream()));
222

223 224
               if (!m_localServer->hasPendingConnections())
                   m_localServer->waitForNewConnection(10000);
225

226 227 228
               m_thirdSocket = m_localServer->nextPendingConnection();
               connect(m_thirdSocket.data(), SIGNAL(readyRead()), this, SLOT(readThirdDataStream()));
           }
229

230
       } else {
231 232 233 234 235
           QMessageBox::warning(0, tr("Cannot Start QML Puppet Executable"),
                                tr("The executable of the QML Puppet process (%1) cannot be started. "
                                   "Please check your installation. "
                                   "QML Puppet is a process which runs in the background to render the items.").
                                arg(applicationPath));
236
       }
237

238 239 240
       m_localServer->close();

   } else {
241
           QMessageBox::warning(0, tr("Cannot Find QML Puppet Executable"), missingQmlPuppetErrorMessage(applicationPath));
242
   }
243 244 245 246
}

NodeInstanceServerProxy::~NodeInstanceServerProxy()
{
247 248
    disconnect(this, SLOT(processFinished(int,QProcess::ExitStatus)));

249 250
    writeCommand(QVariant::fromValue(EndPuppetCommand()));

251 252 253 254 255 256
    if (m_firstSocket)
        m_firstSocket->close();

    if (m_secondSocket)
        m_secondSocket->close();

257
    if (m_thirdSocket)
258 259
        m_thirdSocket->close();

260

261
    if (m_qmlPuppetEditorProcess)
262
        QTimer::singleShot(3000, m_qmlPuppetEditorProcess.data(), SLOT(terminate()));
263

264
    if (m_qmlPuppetPreviewProcess)
265
        QTimer::singleShot(3000, m_qmlPuppetPreviewProcess.data(), SLOT(terminate()));
266 267

    if (m_qmlPuppetRenderProcess)
268
         QTimer::singleShot(3000, m_qmlPuppetRenderProcess.data(), SLOT(terminate()));
269 270 271 272 273 274 275
}

void NodeInstanceServerProxy::dispatchCommand(const QVariant &command)
{
    static const int informationChangedCommandType = QMetaType::type("InformationChangedCommand");
    static const int valuesChangedCommandType = QMetaType::type("ValuesChangedCommand");
    static const int pixmapChangedCommandType = QMetaType::type("PixmapChangedCommand");
276
    static const int childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
277
    static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
278
    static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
279
    static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
280
    static const int tokenCommandType = QMetaType::type("TokenCommand");
Marco Bubke's avatar
Marco Bubke committed
281
    static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
282 283 284 285 286 287 288

    if (command.userType() ==  informationChangedCommandType)
        nodeInstanceClient()->informationChanged(command.value<InformationChangedCommand>());
    else if (command.userType() ==  valuesChangedCommandType)
        nodeInstanceClient()->valuesChanged(command.value<ValuesChangedCommand>());
    else if (command.userType() ==  pixmapChangedCommandType)
        nodeInstanceClient()->pixmapChanged(command.value<PixmapChangedCommand>());
289 290
    else if (command.userType() == childrenChangedCommandType)
        nodeInstanceClient()->childrenChanged(command.value<ChildrenChangedCommand>());
291 292
    else if (command.userType() == statePreviewImageChangedCommandType)
        nodeInstanceClient()->statePreviewImagesChanged(command.value<StatePreviewImageChangedCommand>());
293 294
    else if (command.userType() == componentCompletedCommandType)
        nodeInstanceClient()->componentCompleted(command.value<ComponentCompletedCommand>());
295 296
    else if (command.userType() == tokenCommandType)
        nodeInstanceClient()->token(command.value<TokenCommand>());
Marco Bubke's avatar
Marco Bubke committed
297 298
    else if (command.userType() == debugOutputCommandType)
        nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
299 300 301 302
    else if (command.userType() == synchronizeCommandType) {
        SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
        m_synchronizeId = synchronizeCommand.synchronizeId();
    }  else
303 304 305 306 307 308 309 310
        Q_ASSERT(false);
}

NodeInstanceClientInterface *NodeInstanceServerProxy::nodeInstanceClient() const
{
    return m_nodeInstanceView.data();
}

311 312
QString NodeInstanceServerProxy::missingQmlPuppetErrorMessage(const QString &applicationPath) const
{
313 314 315 316 317 318 319 320
    QString message;
    QTextStream str(&message);
    str << "<html><head/><body><p>"
        << tr("The executable of the QML Puppet process (<code>%1</code>) cannot be found. "
              "Check your installation. "
              "QML Puppet is a process which runs in the background to render the items.").
           arg(QDir::toNativeSeparators(applicationPath))
        << "</p>";
321
    if (hasQtQuick2(m_nodeInstanceView.data())) {
322 323 324 325 326 327 328 329 330
        str << "<p>"
            << tr("You can build <code>qml2puppet</code> yourself with Qt 5.0.1 or higher. "
                 "The source can be found in <code>%1</code>.").
               arg(QDir::toNativeSeparators(sharedDirPath() + QLatin1String("/qml/qmlpuppet/qml2puppet/")))
            << "</p><p>"
            << tr("<code>qml2puppet</code> will be installed to the <code>bin</code> directory of your Qt version. "
                  "Qt Quick Designer will check the <code>bin</code> directory of the currently active Qt version "
                  "of your project.")
            << "</p>";
331
    }
332
    str << "</p></body></html>";
333 334 335
    return message;
}

336
static void writeCommandToSocket(const QVariant &command, QLocalSocket *socket, unsigned int commandCounter)
337
{
338
    if (socket) {
339 340
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
341
        out.setVersion(QDataStream::Qt_4_8);
342
        out << quint32(0);
343
        out << quint32(commandCounter);
344 345 346 347 348 349
        out << command;
        out.device()->seek(0);
        out << quint32(block.size() - sizeof(quint32));

        socket->write(block);
    }
350 351 352 353
}

void NodeInstanceServerProxy::writeCommand(const QVariant &command)
{
354 355 356 357
    writeCommandToSocket(command, m_firstSocket.data(), m_writeCommandCounter);
    writeCommandToSocket(command, m_secondSocket.data(), m_writeCommandCounter);
    writeCommandToSocket(command, m_thirdSocket.data(), m_writeCommandCounter);
    m_writeCommandCounter++;
358 359 360 361 362
    if (m_runModus == TestModus) {
        static int synchronizeId = 0;
        synchronizeId++;
        SynchronizeCommand synchronizeCommand(synchronizeId);

363 364
        writeCommandToSocket(QVariant::fromValue(synchronizeCommand), m_firstSocket.data(), m_writeCommandCounter);
        m_writeCommandCounter++;
365

366
        while (m_firstSocket->waitForReadyRead(100)) {
367 368 369 370 371
                readFirstDataStream();
                if (m_synchronizeId == synchronizeId)
                    return;
        }
    }
372 373
}

374
void NodeInstanceServerProxy::processFinished(int /*exitCode*/, QProcess::ExitStatus exitStatus)
375
{
376
    qDebug() << "Process finished:" << sender();
377 378 379

    writeCommand(QVariant::fromValue(EndPuppetCommand()));

380 381 382 383
    if (m_firstSocket)
        m_firstSocket->close();
    if (m_secondSocket)
        m_secondSocket->close();
384 385 386
    if (m_thirdSocket)
        m_thirdSocket->close();

387 388
    if (exitStatus == QProcess::CrashExit)
        emit processCrashed();
389 390
}

391

392 393 394 395 396 397 398 399 400
void NodeInstanceServerProxy::readFirstDataStream()
{
    QList<QVariant> commandList;

    while (!m_firstSocket->atEnd()) {
        if (m_firstSocket->bytesAvailable() < int(sizeof(quint32)))
            break;

        QDataStream in(m_firstSocket.data());
401
        in.setVersion(QDataStream::Qt_4_8);
402

403
        if (m_firstBlockSize == 0)
404 405 406 407 408
            in >> m_firstBlockSize;

        if (m_firstSocket->bytesAvailable() < m_firstBlockSize)
            break;

409 410 411 412 413 414 415 416
        quint32 commandCounter;
        in >> commandCounter;
        bool commandLost = !((m_firstLastReadCommandCounter == 0 && commandCounter == 0) || (m_firstLastReadCommandCounter + 1 == commandCounter));
        if (commandLost)
            qDebug() << "server command lost: " << m_firstLastReadCommandCounter <<  commandCounter;
        m_firstLastReadCommandCounter = commandCounter;


417 418 419 420 421 422 423 424 425 426 427 428 429
        QVariant command;
        in >> command;
        m_firstBlockSize = 0;

        commandList.append(command);
    }

    foreach (const QVariant &command, commandList) {
        dispatchCommand(command);
    }
}

void NodeInstanceServerProxy::readSecondDataStream()
430 431 432
{
    QList<QVariant> commandList;

433 434
    while (!m_secondSocket->atEnd()) {
        if (m_secondSocket->bytesAvailable() < int(sizeof(quint32)))
435 436
            break;

437
        QDataStream in(m_secondSocket.data());
438
        in.setVersion(QDataStream::Qt_4_8);
439

440
        if (m_secondBlockSize == 0)
441
            in >> m_secondBlockSize;
442

443
        if (m_secondSocket->bytesAvailable() < m_secondBlockSize)
444 445
            break;

446 447 448 449 450 451 452 453
        quint32 commandCounter;
        in >> commandCounter;
        bool commandLost = !((m_secondLastReadCommandCounter == 0 && commandCounter == 0) || (m_secondLastReadCommandCounter + 1 == commandCounter));
        if (commandLost)
            qDebug() << "server command lost: " << m_secondLastReadCommandCounter <<  commandCounter;
        m_secondLastReadCommandCounter = commandCounter;


454 455
        QVariant command;
        in >> command;
456
        m_secondBlockSize = 0;
457 458 459 460 461 462 463 464 465

        commandList.append(command);
    }

    foreach (const QVariant &command, commandList) {
        dispatchCommand(command);
    }
}

466 467 468 469 470 471 472 473 474
void NodeInstanceServerProxy::readThirdDataStream()
{
    QList<QVariant> commandList;

    while (!m_thirdSocket->atEnd()) {
        if (m_thirdSocket->bytesAvailable() < int(sizeof(quint32)))
            break;

        QDataStream in(m_thirdSocket.data());
475
        in.setVersion(QDataStream::Qt_4_8);
476

477
        if (m_thirdBlockSize == 0)
478 479 480 481 482
            in >> m_thirdBlockSize;

        if (m_thirdSocket->bytesAvailable() < m_thirdBlockSize)
            break;

483 484 485 486 487 488 489 490
        quint32 commandCounter;
        in >> commandCounter;
        bool commandLost = !((m_thirdLastReadCommandCounter == 0 && commandCounter == 0) || (m_thirdLastReadCommandCounter + 1 == commandCounter));
        if (commandLost)
            qDebug() << "server command lost: " << m_thirdLastReadCommandCounter <<  commandCounter;
        m_thirdLastReadCommandCounter = commandCounter;


491 492 493 494 495 496 497 498 499 500 501 502
        QVariant command;
        in >> command;
        m_thirdBlockSize = 0;

        commandList.append(command);
    }

    foreach (const QVariant &command, commandList) {
        dispatchCommand(command);
    }
}

503 504
QString NodeInstanceServerProxy::qmlPuppetApplicationName() const
{
505 506 507
    if (hasQtQuick2(m_nodeInstanceView.data()))
        return QLatin1String("qml2puppet" QTC_HOST_EXE_SUFFIX);
    return QLatin1String("qmlpuppet" QTC_HOST_EXE_SUFFIX);
508 509 510 511 512
}

QString NodeInstanceServerProxy::macOSBundlePath(const QString &path) const
{
    QString applicationPath = path;
513 514 515 516 517 518 519
    if (Utils::HostOsInfo::isMacHost()) {
        if (hasQtQuick2(m_nodeInstanceView.data()))
            applicationPath += QLatin1String("/qml2puppet.app/Contents/MacOS");
        else
            applicationPath += QLatin1String("/qmlpuppet.app/Contents/MacOS");

    }
520 521
   return applicationPath;
}
522

523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
void NodeInstanceServerProxy::createInstances(const CreateInstancesCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::changeFileUrl(const ChangeFileUrlCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::createScene(const CreateSceneCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::clearScene(const ClearSceneCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::removeInstances(const RemoveInstancesCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::removeProperties(const RemovePropertiesCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::changePropertyBindings(const ChangeBindingsCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::changePropertyValues(const ChangeValuesCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

563 564 565 566 567
void NodeInstanceServerProxy::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
void NodeInstanceServerProxy::reparentInstances(const ReparentInstancesCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::changeIds(const ChangeIdsCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

void NodeInstanceServerProxy::changeState(const ChangeStateCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

583 584 585 586
void NodeInstanceServerProxy::completeComponent(const CompleteComponentCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}
587

588
void NodeInstanceServerProxy::changeNodeSource(const ChangeNodeSourceCommand &command)
589 590 591 592
{
    writeCommand(QVariant::fromValue(command));
}

593 594 595 596 597
void NodeInstanceServerProxy::token(const TokenCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

598 599 600 601 602
void NodeInstanceServerProxy::removeSharedMemory(const RemoveSharedMemoryCommand &command)
{
   writeCommand(QVariant::fromValue(command));
}

603
} // namespace QmlDesigner