nodeinstanceserverproxy.cpp 21.1 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 <QTimer>
39 40 41 42 43 44 45 46 47

#include "propertyabstractcontainer.h"
#include "propertyvaluecontainer.h"
#include "propertybindingcontainer.h"
#include "instancecontainer.h"
#include "createinstancescommand.h"
#include "createscenecommand.h"
#include "changevaluescommand.h"
#include "changebindingscommand.h"
48
#include "changeauxiliarycommand.h"
49 50 51 52 53 54 55
#include "changefileurlcommand.h"
#include "removeinstancescommand.h"
#include "clearscenecommand.h"
#include "removepropertiescommand.h"
#include "reparentinstancescommand.h"
#include "changeidscommand.h"
#include "changestatecommand.h"
56
#include "completecomponentcommand.h"
57
#include "changenodesourcecommand.h"
58 59 60 61

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

72
#include "nodeinstanceview.h"
73 74

#include "import.h"
75 76 77

#include <utils/hostosinfo.h>

78 79
#include <QMessageBox>

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

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

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

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

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

namespace QmlDesigner {

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

    return false;
}

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

   m_localServer->listen(socketToken);
140
   m_localServer->setMaxPendingConnections(3);
141

142 143
   QString applicationPath =  pathToQt + QLatin1String("/bin");
   if (runModus == TestModus) {
144
       applicationPath = QCoreApplication::applicationDirPath()
145 146
           + qmlPuppetApplicationDirectoryForTests()
           + qmlPuppetApplicationName();
147
   } else {
148
       applicationPath = macOSBundlePath(applicationPath);
Robert Loehning's avatar
Robert Loehning committed
149
       applicationPath += QLatin1Char('/') + qmlPuppetApplicationName();
150 151 152 153
       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
154
           applicationPath += QLatin1Char('/') + qmlPuppetApplicationName();
155
       }
156
   }
157

158
   QByteArray envImportPath = qgetenv("QTCREATOR_QMLPUPPET_PATH");
159
   if (!envImportPath.isEmpty())
160 161
       applicationPath = envImportPath;

162 163
   QProcessEnvironment enviroment = QProcessEnvironment::systemEnvironment();

164 165
   if (QFileInfo(applicationPath).exists()) {
       m_qmlPuppetEditorProcess = new QProcess;
166 167
       m_qmlPuppetEditorProcess->setProcessEnvironment(enviroment);
       m_qmlPuppetEditorProcess->setObjectName("EditorProcess");
168 169 170
       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();
171
       if (fowardQmlpuppetOutput)
172 173
           m_qmlPuppetEditorProcess->setProcessChannelMode(QProcess::ForwardedChannels);
       m_qmlPuppetEditorProcess->start(applicationPath, QStringList() << socketToken << "editormode" << "-graphicssystem raster");
174

175 176
       if (runModus == NormalModus) {
           m_qmlPuppetPreviewProcess = new QProcess;
177 178
           m_qmlPuppetPreviewProcess->setProcessEnvironment(enviroment);
           m_qmlPuppetPreviewProcess->setObjectName("PreviewProcess");
179 180 181 182 183
           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");
184

185
           m_qmlPuppetRenderProcess = new QProcess;
186 187
           m_qmlPuppetRenderProcess->setProcessEnvironment(enviroment);
           m_qmlPuppetRenderProcess->setObjectName("RenderProcess");
188 189 190 191 192
           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");
193

194
       }
195

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

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

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

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

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

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

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

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

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

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

229
       } else {
230
               QMessageBox::warning(0, tr("Cannot Start QML Puppet Executable"), missingQmlPuppetErrorMessage(applicationPath));
231
       }
232

233 234 235
       m_localServer->close();

   } else {
236
           QMessageBox::warning(0, tr("Cannot Find QML Puppet Executable"), missingQmlPuppetErrorMessage(applicationPath));
237
   }
238 239 240 241
}

NodeInstanceServerProxy::~NodeInstanceServerProxy()
{
242 243
    disconnect(this, SLOT(processFinished(int,QProcess::ExitStatus)));

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

246 247 248 249 250 251
    if (m_firstSocket)
        m_firstSocket->close();

    if (m_secondSocket)
        m_secondSocket->close();

252
    if (m_thirdSocket)
253 254
        m_thirdSocket->close();

255

256
    if (m_qmlPuppetEditorProcess)
257
        QTimer::singleShot(3000, m_qmlPuppetEditorProcess.data(), SLOT(terminate()));
258

259
    if (m_qmlPuppetPreviewProcess)
260
        QTimer::singleShot(3000, m_qmlPuppetPreviewProcess.data(), SLOT(terminate()));
261 262

    if (m_qmlPuppetRenderProcess)
263
         QTimer::singleShot(3000, m_qmlPuppetRenderProcess.data(), SLOT(terminate()));
264 265 266 267 268 269 270
}

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");
271
    static const int childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
272
    static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
273
    static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
274
    static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
275
    static const int tokenCommandType = QMetaType::type("TokenCommand");
Marco Bubke's avatar
Marco Bubke committed
276
    static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
277 278 279 280 281 282 283

    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>());
284 285
    else if (command.userType() == childrenChangedCommandType)
        nodeInstanceClient()->childrenChanged(command.value<ChildrenChangedCommand>());
286 287
    else if (command.userType() == statePreviewImageChangedCommandType)
        nodeInstanceClient()->statePreviewImagesChanged(command.value<StatePreviewImageChangedCommand>());
288 289
    else if (command.userType() == componentCompletedCommandType)
        nodeInstanceClient()->componentCompleted(command.value<ComponentCompletedCommand>());
290 291
    else if (command.userType() == tokenCommandType)
        nodeInstanceClient()->token(command.value<TokenCommand>());
Marco Bubke's avatar
Marco Bubke committed
292 293
    else if (command.userType() == debugOutputCommandType)
        nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
294 295 296 297
    else if (command.userType() == synchronizeCommandType) {
        SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
        m_synchronizeId = synchronizeCommand.synchronizeId();
    }  else
298 299 300 301 302 303 304 305
        Q_ASSERT(false);
}

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

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
QString NodeInstanceServerProxy::missingQmlPuppetErrorMessage(const QString &applicationPath) const
{
    QString message = tr("The executable of the QML Puppet process (%1) cannot be found."
       "Check your installation."
       "QML Puppet is a process which runs in the background to render the items.").
    arg(applicationPath);
    if (hasQtQuick2(m_nodeInstanceView.data())) {
        message += tr("You can build qml2puppet yourself with Qt 5.0.1 or higher"
                      "The source can be found in %1/qml/qmlpuppet/qml2puppet/").arg(sharedDirPath());
        message += tr("The qml2puppet will get installed to the bin directory of your Qt."
                      "Qt Quick Designer will check the bin direcotry of the Qt currently active"
                      "for your project.");

    }

    return message;
}

324
static void writeCommandToSocket(const QVariant &command, QLocalSocket *socket, unsigned int commandCounter)
325
{
326
    if (socket) {
327 328
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
329
        out.setVersion(QDataStream::Qt_4_8);
330
        out << quint32(0);
331
        out << quint32(commandCounter);
332 333 334 335 336 337
        out << command;
        out.device()->seek(0);
        out << quint32(block.size() - sizeof(quint32));

        socket->write(block);
    }
338 339 340 341
}

void NodeInstanceServerProxy::writeCommand(const QVariant &command)
{
342 343 344 345
    writeCommandToSocket(command, m_firstSocket.data(), m_writeCommandCounter);
    writeCommandToSocket(command, m_secondSocket.data(), m_writeCommandCounter);
    writeCommandToSocket(command, m_thirdSocket.data(), m_writeCommandCounter);
    m_writeCommandCounter++;
346 347 348 349 350
    if (m_runModus == TestModus) {
        static int synchronizeId = 0;
        synchronizeId++;
        SynchronizeCommand synchronizeCommand(synchronizeId);

351 352
        writeCommandToSocket(QVariant::fromValue(synchronizeCommand), m_firstSocket.data(), m_writeCommandCounter);
        m_writeCommandCounter++;
353

354
        while (m_firstSocket->waitForReadyRead(100)) {
355 356 357 358 359
                readFirstDataStream();
                if (m_synchronizeId == synchronizeId)
                    return;
        }
    }
360 361
}

362
void NodeInstanceServerProxy::processFinished(int /*exitCode*/, QProcess::ExitStatus exitStatus)
363
{
364
    qDebug() << "Process finished:" << sender();
365 366 367

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

368 369 370 371
    if (m_firstSocket)
        m_firstSocket->close();
    if (m_secondSocket)
        m_secondSocket->close();
372 373 374
    if (m_thirdSocket)
        m_thirdSocket->close();

375 376
    if (exitStatus == QProcess::CrashExit)
        emit processCrashed();
377 378
}

379

380 381 382 383 384 385 386 387 388
void NodeInstanceServerProxy::readFirstDataStream()
{
    QList<QVariant> commandList;

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

        QDataStream in(m_firstSocket.data());
389
        in.setVersion(QDataStream::Qt_4_8);
390

391
        if (m_firstBlockSize == 0)
392 393 394 395 396
            in >> m_firstBlockSize;

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

397 398 399 400 401 402 403 404
        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;


405 406 407 408 409 410 411 412 413 414 415 416 417
        QVariant command;
        in >> command;
        m_firstBlockSize = 0;

        commandList.append(command);
    }

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

void NodeInstanceServerProxy::readSecondDataStream()
418 419 420
{
    QList<QVariant> commandList;

421 422
    while (!m_secondSocket->atEnd()) {
        if (m_secondSocket->bytesAvailable() < int(sizeof(quint32)))
423 424
            break;

425
        QDataStream in(m_secondSocket.data());
426
        in.setVersion(QDataStream::Qt_4_8);
427

428
        if (m_secondBlockSize == 0)
429
            in >> m_secondBlockSize;
430

431
        if (m_secondSocket->bytesAvailable() < m_secondBlockSize)
432 433
            break;

434 435 436 437 438 439 440 441
        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;


442 443
        QVariant command;
        in >> command;
444
        m_secondBlockSize = 0;
445 446 447 448 449 450 451 452 453

        commandList.append(command);
    }

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

454 455 456 457 458 459 460 461 462
void NodeInstanceServerProxy::readThirdDataStream()
{
    QList<QVariant> commandList;

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

        QDataStream in(m_thirdSocket.data());
463
        in.setVersion(QDataStream::Qt_4_8);
464

465
        if (m_thirdBlockSize == 0)
466 467 468 469 470
            in >> m_thirdBlockSize;

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

471 472 473 474 475 476 477 478
        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;


479 480 481 482 483 484 485 486 487 488 489 490
        QVariant command;
        in >> command;
        m_thirdBlockSize = 0;

        commandList.append(command);
    }

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

491 492
QString NodeInstanceServerProxy::qmlPuppetApplicationName() const
{
493 494 495
    if (hasQtQuick2(m_nodeInstanceView.data()))
        return QLatin1String("qml2puppet" QTC_HOST_EXE_SUFFIX);
    return QLatin1String("qmlpuppet" QTC_HOST_EXE_SUFFIX);
496 497 498 499 500
}

QString NodeInstanceServerProxy::macOSBundlePath(const QString &path) const
{
    QString applicationPath = path;
501 502
    if (Utils::HostOsInfo::isMacHost())
        applicationPath += QLatin1String("/qmlpuppet.app/Contents/MacOS");
503 504
   return applicationPath;
}
505

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
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));
}

546 547 548 549 550
void NodeInstanceServerProxy::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
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));
}

566 567 568 569
void NodeInstanceServerProxy::completeComponent(const CompleteComponentCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}
570

571
void NodeInstanceServerProxy::changeNodeSource(const ChangeNodeSourceCommand &command)
572 573 574 575
{
    writeCommand(QVariant::fromValue(command));
}

576 577 578 579 580
void NodeInstanceServerProxy::token(const TokenCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

581 582 583 584 585
void NodeInstanceServerProxy::removeSharedMemory(const RemoveSharedMemoryCommand &command)
{
   writeCommand(QVariant::fromValue(command));
}

586
} // namespace QmlDesigner