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