nodeinstanceserverproxy.cpp 24.5 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
#include <QMessageBox>
42 43 44 45 46

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

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

70
#include "nodeinstanceview.h"
71 72

#include "import.h"
73 74 75

#include <utils/hostosinfo.h>

76 77
#include <QMessageBox>

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

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

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

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

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

namespace QmlDesigner {

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

    return false;
}

120 121 122 123 124 125 126 127 128
QString NodeInstanceServerProxy::creatorQmlPuppetPath()
{
    QString applicationPath =  QCoreApplication::applicationDirPath();
    applicationPath = macOSBundlePath(applicationPath);
    applicationPath += QLatin1Char('/') + qmlPuppetApplicationName();

    return applicationPath;
}

129
NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView, RunModus runModus, const QString &pathToQt)
130 131 132
    : NodeInstanceServerInterface(nodeInstanceView),
      m_localServer(new QLocalServer(this)),
      m_nodeInstanceView(nodeInstanceView),
133
      m_firstBlockSize(0),
134
      m_secondBlockSize(0),
135
      m_thirdBlockSize(0),
136 137 138 139
      m_writeCommandCounter(0),
      m_firstLastReadCommandCounter(0),
      m_secondLastReadCommandCounter(0),
      m_thirdLastReadCommandCounter(0),
140 141
      m_runModus(runModus),
      m_synchronizeId(-1)
142 143 144 145
{
   QString socketToken(QUuid::createUuid().toString());

   m_localServer->listen(socketToken);
146
   m_localServer->setMaxPendingConnections(3);
147

148 149
   QString applicationPath =  pathToQt + QLatin1String("/bin");
   if (runModus == TestModus) {
150
       applicationPath = QCoreApplication::applicationDirPath()
151 152
           + qmlPuppetApplicationDirectoryForTests()
           + qmlPuppetApplicationName();
153
   } else {
154
       applicationPath = macOSBundlePath(applicationPath);
Robert Loehning's avatar
Robert Loehning committed
155
       applicationPath += QLatin1Char('/') + qmlPuppetApplicationName();
156
#ifdef QT_NO_DEBUG // to prevent of choosing the wrong puppet in debug
157 158
       if (!QFileInfo(applicationPath).exists()) { //No qmlpuppet in Qt
           //We have to find out how to give not too intrusive feedback
159
           applicationPath = creatorQmlPuppetPath();
160
       }
161
#endif
162
   }
163

164

165
   QByteArray envImportPath = qgetenv("QTCREATOR_QMLPUPPET_PATH");
166
   if (!envImportPath.isEmpty())
167 168
       applicationPath = envImportPath;

169
   QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
170

171
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) && (defined(Q_OS_MAC) || defined(Q_OS_LINUX))
Laurent Montel's avatar
Laurent Montel committed
172
   environment.insert(QLatin1String("DESIGNER_DONT_USE_SHARED_MEMORY"), QLatin1String("1"));
173 174
#endif

175 176
   if (QFileInfo(applicationPath).exists()) {
       m_qmlPuppetEditorProcess = new QProcess;
177
       m_qmlPuppetEditorProcess->setProcessEnvironment(environment);
178
       m_qmlPuppetEditorProcess->setObjectName("EditorProcess");
179 180 181
       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();
182 183 184 185
       if (fowardQmlpuppetOutput) {
           m_qmlPuppetEditorProcess->setProcessChannelMode(QProcess::MergedChannels);
           connect(m_qmlPuppetEditorProcess.data(), SIGNAL(readyRead()), this, SLOT(printEditorProcessOutput()));
       }
186
       m_qmlPuppetEditorProcess->start(applicationPath, QStringList() << socketToken << "editormode" << "-graphicssystem raster");
187

188 189
       if (runModus == NormalModus) {
           m_qmlPuppetPreviewProcess = new QProcess;
190
           m_qmlPuppetPreviewProcess->setProcessEnvironment(environment);
191
           m_qmlPuppetPreviewProcess->setObjectName("PreviewProcess");
192 193
           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()));
194 195 196 197
           if (fowardQmlpuppetOutput) {
               m_qmlPuppetPreviewProcess->setProcessChannelMode(QProcess::MergedChannels);
               connect(m_qmlPuppetPreviewProcess.data(), SIGNAL(readyRead()), this, SLOT(printPreviewProcessOutput()));
           }
198
           m_qmlPuppetPreviewProcess->start(applicationPath, QStringList() << socketToken << "previewmode" << "-graphicssystem raster");
199

200
           m_qmlPuppetRenderProcess = new QProcess;
201
           m_qmlPuppetRenderProcess->setProcessEnvironment(environment);
202
           m_qmlPuppetRenderProcess->setObjectName("RenderProcess");
203 204
           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()));
205 206 207 208
           if (fowardQmlpuppetOutput) {
               m_qmlPuppetRenderProcess->setProcessChannelMode(QProcess::MergedChannels);
               connect(m_qmlPuppetRenderProcess.data(), SIGNAL(readyRead()), this, SLOT(printRenderProcessOutput()));
           }
209
           m_qmlPuppetRenderProcess->start(applicationPath, QStringList() << socketToken << "rendermode" << "-graphicssystem raster");
210

211
       }
212

213
       connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
214

215 216
       if (m_qmlPuppetEditorProcess->waitForStarted(10000)) {
           connect(m_qmlPuppetEditorProcess.data(), SIGNAL(finished(int)), m_qmlPuppetEditorProcess.data(),SLOT(deleteLater()));
217

218 219 220
           if (runModus == NormalModus) {
               m_qmlPuppetPreviewProcess->waitForStarted();
               connect(m_qmlPuppetPreviewProcess.data(), SIGNAL(finished(int)), m_qmlPuppetPreviewProcess.data(),SLOT(deleteLater()));
221

222 223 224
               m_qmlPuppetRenderProcess->waitForStarted();
               connect(m_qmlPuppetRenderProcess.data(), SIGNAL(finished(int)), m_qmlPuppetRenderProcess.data(),SLOT(deleteLater()));
           }
225

226 227
           if (!m_localServer->hasPendingConnections())
               m_localServer->waitForNewConnection(10000);
228

229 230
           m_firstSocket = m_localServer->nextPendingConnection();
           connect(m_firstSocket.data(), SIGNAL(readyRead()), this, SLOT(readFirstDataStream()));
231

232 233 234
           if (runModus == NormalModus) {
               if (!m_localServer->hasPendingConnections())
                   m_localServer->waitForNewConnection(10000);
235

236 237
               m_secondSocket = m_localServer->nextPendingConnection();
               connect(m_secondSocket.data(), SIGNAL(readyRead()), this, SLOT(readSecondDataStream()));
238

239 240
               if (!m_localServer->hasPendingConnections())
                   m_localServer->waitForNewConnection(10000);
241

242 243 244
               m_thirdSocket = m_localServer->nextPendingConnection();
               connect(m_thirdSocket.data(), SIGNAL(readyRead()), this, SLOT(readThirdDataStream()));
           }
245

246
       } else {
247 248 249 250 251
           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));
252
       }
253

254 255 256
       m_localServer->close();

   } else {
257
           QMessageBox::warning(0, tr("Cannot Find QML Puppet Executable"), missingQmlPuppetErrorMessage(applicationPath));
258
   }
259 260 261 262 263 264 265

   int indexOfCapturePuppetStream = QCoreApplication::arguments().indexOf("-capture-puppet-stream");
   if (indexOfCapturePuppetStream > 0) {
       m_captureFileForTest.setFileName(QCoreApplication::arguments().at(indexOfCapturePuppetStream + 1));
       bool isOpen = m_captureFileForTest.open(QIODevice::WriteOnly);
       qDebug() << "file is open: " << isOpen;
   }
266 267 268 269
}

NodeInstanceServerProxy::~NodeInstanceServerProxy()
{
270 271
    disconnect(this, SLOT(processFinished(int,QProcess::ExitStatus)));

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

274 275 276 277 278 279
    if (m_firstSocket)
        m_firstSocket->close();

    if (m_secondSocket)
        m_secondSocket->close();

280
    if (m_thirdSocket)
281 282
        m_thirdSocket->close();

283

284
    if (m_qmlPuppetEditorProcess)
285
        QTimer::singleShot(3000, m_qmlPuppetEditorProcess.data(), SLOT(terminate()));
286

287
    if (m_qmlPuppetPreviewProcess)
288
        QTimer::singleShot(3000, m_qmlPuppetPreviewProcess.data(), SLOT(terminate()));
289 290

    if (m_qmlPuppetRenderProcess)
291
         QTimer::singleShot(3000, m_qmlPuppetRenderProcess.data(), SLOT(terminate()));
292 293 294 295 296 297 298
}

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");
299
    static const int childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
300
    static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
301
    static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
302
    static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
303
    static const int tokenCommandType = QMetaType::type("TokenCommand");
Marco Bubke's avatar
Marco Bubke committed
304
    static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
305

306
    if (command.userType() ==  informationChangedCommandType) {
307
        nodeInstanceClient()->informationChanged(command.value<InformationChangedCommand>());
308
    } else if (command.userType() ==  valuesChangedCommandType) {
309
        nodeInstanceClient()->valuesChanged(command.value<ValuesChangedCommand>());
310
    } else if (command.userType() ==  pixmapChangedCommandType) {
311
        nodeInstanceClient()->pixmapChanged(command.value<PixmapChangedCommand>());
312
    } else if (command.userType() == childrenChangedCommandType) {
313
        nodeInstanceClient()->childrenChanged(command.value<ChildrenChangedCommand>());
314
    } else if (command.userType() == statePreviewImageChangedCommandType) {
315
        nodeInstanceClient()->statePreviewImagesChanged(command.value<StatePreviewImageChangedCommand>());
316
    } else if (command.userType() == componentCompletedCommandType) {
317
        nodeInstanceClient()->componentCompleted(command.value<ComponentCompletedCommand>());
318
    } else if (command.userType() == tokenCommandType) {
319
        nodeInstanceClient()->token(command.value<TokenCommand>());
320
    } else if (command.userType() == debugOutputCommandType) {
Marco Bubke's avatar
Marco Bubke committed
321
        nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
322
    } else if (command.userType() == synchronizeCommandType) {
323 324 325
        SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
        m_synchronizeId = synchronizeCommand.synchronizeId();
    }  else
326 327 328 329 330 331 332 333
        Q_ASSERT(false);
}

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

334 335
QString NodeInstanceServerProxy::missingQmlPuppetErrorMessage(const QString &applicationPath) const
{
336 337 338 339 340 341 342 343
    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>";
344
    if (hasQtQuick2(m_nodeInstanceView.data())) {
345 346 347 348 349 350 351 352 353
        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>";
354
    }
355
    str << "</p></body></html>";
356 357 358
    return message;
}

359
static void writeCommandToIODecive(const QVariant &command, QIODevice *ioDevice, unsigned int commandCounter)
360
{
361
    if (ioDevice) {
362 363
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
364
        out.setVersion(QDataStream::Qt_4_8);
365
        out << quint32(0);
366
        out << quint32(commandCounter);
367 368 369 370
        out << command;
        out.device()->seek(0);
        out << quint32(block.size() - sizeof(quint32));

371
        ioDevice->write(block);
372
    }
373 374 375 376
}

void NodeInstanceServerProxy::writeCommand(const QVariant &command)
{
377 378 379 380 381 382 383 384 385 386
    writeCommandToIODecive(command, m_firstSocket.data(), m_writeCommandCounter);
    writeCommandToIODecive(command, m_secondSocket.data(), m_writeCommandCounter);
    writeCommandToIODecive(command, m_thirdSocket.data(), m_writeCommandCounter);

    if (m_captureFileForTest.isWritable()) {
        qDebug() << "Write strean to file: " << m_captureFileForTest.fileName();
        writeCommandToIODecive(command, &m_captureFileForTest, m_writeCommandCounter);
        qDebug() << "\twrite file: " << m_captureFileForTest.pos();
    }

387
    m_writeCommandCounter++;
388 389 390 391 392
    if (m_runModus == TestModus) {
        static int synchronizeId = 0;
        synchronizeId++;
        SynchronizeCommand synchronizeCommand(synchronizeId);

393
        writeCommandToIODecive(QVariant::fromValue(synchronizeCommand), m_firstSocket.data(), m_writeCommandCounter);
394
        m_writeCommandCounter++;
395

396
        while (m_firstSocket->waitForReadyRead(100)) {
397 398 399 400 401
                readFirstDataStream();
                if (m_synchronizeId == synchronizeId)
                    return;
        }
    }
402 403
}

404
void NodeInstanceServerProxy::processFinished(int /*exitCode*/, QProcess::ExitStatus exitStatus)
405
{
406
    qDebug() << "Process finished:" << sender();
407

408 409 410
    if (m_captureFileForTest.isOpen()) {
        m_captureFileForTest.close();
        m_captureFileForTest.remove();
411 412
        QMessageBox::warning(0, tr("QML Puppet Crashed"), tr("Your are recording a Puppet stream and the puppet crashed. "
                                                             "It is recommended to reopen the QML Designer and start again."));
413 414 415
    }


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

418 419 420 421
    if (m_firstSocket)
        m_firstSocket->close();
    if (m_secondSocket)
        m_secondSocket->close();
422 423 424
    if (m_thirdSocket)
        m_thirdSocket->close();

425 426
    if (exitStatus == QProcess::CrashExit)
        emit processCrashed();
427 428
}

429

430 431 432 433 434 435 436 437 438
void NodeInstanceServerProxy::readFirstDataStream()
{
    QList<QVariant> commandList;

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

        QDataStream in(m_firstSocket.data());
439
        in.setVersion(QDataStream::Qt_4_8);
440

441
        if (m_firstBlockSize == 0)
442 443 444 445 446
            in >> m_firstBlockSize;

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

447 448 449 450 451 452 453 454
        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;


455 456 457 458 459 460 461 462 463 464 465 466 467
        QVariant command;
        in >> command;
        m_firstBlockSize = 0;

        commandList.append(command);
    }

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

void NodeInstanceServerProxy::readSecondDataStream()
468 469 470
{
    QList<QVariant> commandList;

471 472
    while (!m_secondSocket->atEnd()) {
        if (m_secondSocket->bytesAvailable() < int(sizeof(quint32)))
473 474
            break;

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

478
        if (m_secondBlockSize == 0)
479
            in >> m_secondBlockSize;
480

481
        if (m_secondSocket->bytesAvailable() < m_secondBlockSize)
482 483
            break;

484 485 486 487 488 489 490 491
        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;


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

        commandList.append(command);
    }

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

504 505 506 507 508 509 510 511 512
void NodeInstanceServerProxy::readThirdDataStream()
{
    QList<QVariant> commandList;

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

        QDataStream in(m_thirdSocket.data());
513
        in.setVersion(QDataStream::Qt_4_8);
514

515
        if (m_thirdBlockSize == 0)
516 517 518 519 520
            in >> m_thirdBlockSize;

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

521 522 523 524 525 526 527 528
        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;


529 530 531 532 533 534 535 536 537 538 539 540
        QVariant command;
        in >> command;
        m_thirdBlockSize = 0;

        commandList.append(command);
    }

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

541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
void NodeInstanceServerProxy::printEditorProcessOutput()
{
    while (m_qmlPuppetEditorProcess->canReadLine()) {
        QByteArray line = m_qmlPuppetEditorProcess->readLine();
        line.chop(1);
        qDebug().nospace() << "Editor Puppet: " << qPrintable(line);
    }
    qDebug() << "\n";
}

void NodeInstanceServerProxy::printPreviewProcessOutput()
{
    while (m_qmlPuppetPreviewProcess->canReadLine()) {
        QByteArray line = m_qmlPuppetPreviewProcess->readLine();
        line.chop(1);
        qDebug().nospace() << "Preview Puppet: " << qPrintable(line);
    }
    qDebug() << "\n";
}

void NodeInstanceServerProxy::printRenderProcessOutput()
{
    while (m_qmlPuppetRenderProcess->canReadLine()) {
        QByteArray line = m_qmlPuppetRenderProcess->readLine();
        line.chop(1);
        qDebug().nospace() << "Render Puppet: " << qPrintable(line);
    }

    qDebug() << "\n";
}

572 573
QString NodeInstanceServerProxy::qmlPuppetApplicationName() const
{
574 575 576
    if (hasQtQuick2(m_nodeInstanceView.data()))
        return QLatin1String("qml2puppet" QTC_HOST_EXE_SUFFIX);
    return QLatin1String("qmlpuppet" QTC_HOST_EXE_SUFFIX);
577 578 579 580 581
}

QString NodeInstanceServerProxy::macOSBundlePath(const QString &path) const
{
    QString applicationPath = path;
582 583 584 585 586 587 588
    if (Utils::HostOsInfo::isMacHost()) {
        if (hasQtQuick2(m_nodeInstanceView.data()))
            applicationPath += QLatin1String("/qml2puppet.app/Contents/MacOS");
        else
            applicationPath += QLatin1String("/qmlpuppet.app/Contents/MacOS");

    }
589 590
   return applicationPath;
}
591

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
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));
}

632 633 634 635 636
void NodeInstanceServerProxy::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
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));
}

652 653 654 655
void NodeInstanceServerProxy::completeComponent(const CompleteComponentCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}
656

657
void NodeInstanceServerProxy::changeNodeSource(const ChangeNodeSourceCommand &command)
658 659 660 661
{
    writeCommand(QVariant::fromValue(command));
}

662 663 664 665 666
void NodeInstanceServerProxy::token(const TokenCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}

667 668 669 670 671
void NodeInstanceServerProxy::removeSharedMemory(const RemoveSharedMemoryCommand &command)
{
   writeCommand(QVariant::fromValue(command));
}

672
} // namespace QmlDesigner