nodeinstanceserverproxy.cpp 10.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "nodeinstanceserverproxy.h"

#include <QLocalServer>
#include <QLocalSocket>
#include <QProcess>
#include <QCoreApplication>
#include <QUuid>

#include "propertyabstractcontainer.h"
#include "propertyvaluecontainer.h"
#include "propertybindingcontainer.h"
#include "instancecontainer.h"
#include "createinstancescommand.h"
#include "createscenecommand.h"
#include "changevaluescommand.h"
#include "changebindingscommand.h"
#include "changefileurlcommand.h"
#include "removeinstancescommand.h"
#include "clearscenecommand.h"
#include "removepropertiescommand.h"
#include "reparentinstancescommand.h"
#include "changeidscommand.h"
#include "changestatecommand.h"
24
#include "addimportcommand.h"
25
#include "completecomponentcommand.h"
26
27
28
29

#include "informationchangedcommand.h"
#include "pixmapchangedcommand.h"
#include "valueschangedcommand.h"
30
#include "childrenchangedcommand.h"
31
32
#include "imagecontainer.h"
#include "statepreviewimagechangedcommand.h"
33
#include "componentcompletedcommand.h"
34

35
36
#include "synchronizecommand.h"

37
38
39
40
41
#include "nodeinstanceview.h"
#include "nodeinstanceclientproxy.h"

namespace QmlDesigner {

42
NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView, RunModus runModus)
43
44
45
    : NodeInstanceServerInterface(nodeInstanceView),
      m_localServer(new QLocalServer(this)),
      m_nodeInstanceView(nodeInstanceView),
46
      m_firstBlockSize(0),
47
48
49
      m_secondBlockSize(0),
      m_runModus(runModus),
      m_synchronizeId(-1)
50
51
52
53
{
   QString socketToken(QUuid::createUuid().toString());

   m_localServer->listen(socketToken);
54
55
   m_localServer->setMaxPendingConnections(2);

Marco Bubke's avatar
Marco Bubke committed
56
57
58
   QString applicationPath =  QCoreApplication::applicationDirPath();
   if (runModus == TestModus)
       applicationPath += "/../../../../../bin";
59
60
61
62
63
#ifdef Q_OS_MACX
   applicationPath += "/qmlpuppet.app/Contents/MacOS";
#endif
   applicationPath += "/qmlpuppet";

64
   m_qmlPuppetEditorProcess = new QProcess(this);
65
   connect(m_qmlPuppetEditorProcess.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
66
   connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), m_qmlPuppetEditorProcess.data(), SLOT(kill()));
67
68
69
   bool fowardQmlpuppetOutput = !qgetenv("FORWARD_QMLPUPPET_OUTPUT").isEmpty();
   if (fowardQmlpuppetOutput)
       m_qmlPuppetEditorProcess->setProcessChannelMode(QProcess::ForwardedChannels);
70
   m_qmlPuppetEditorProcess->start(applicationPath, QStringList() << socketToken << "editormode" << "-graphicssystem raster");
71

72
   if (runModus == NormalModus) {
73
       m_qmlPuppetPreviewProcess = new QProcess(this);
74
       connect(m_qmlPuppetPreviewProcess.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(processFinished(int,QProcess::ExitStatus)));
75
       connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), m_qmlPuppetPreviewProcess.data(), SLOT(kill()));
76
77
       if (fowardQmlpuppetOutput)
           m_qmlPuppetPreviewProcess->setProcessChannelMode(QProcess::ForwardedChannels);
78
79
       m_qmlPuppetPreviewProcess->start(applicationPath, QStringList() << socketToken << "previewmode" << "-graphicssystem raster");
   }
80
81

   connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
82
83

   m_qmlPuppetEditorProcess->waitForStarted();
84
85
86
87

   if (runModus == NormalModus) {
       m_qmlPuppetPreviewProcess->waitForStarted();
   }
88
89
90
91
92
93

   if (!m_localServer->hasPendingConnections())
       m_localServer->waitForNewConnection(-1);

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

95
96
97
   if (runModus == NormalModus) {
       if (!m_localServer->hasPendingConnections())
           m_localServer->waitForNewConnection(-1);
98

99
100
101
       m_secondSocket = m_localServer->nextPendingConnection();
       connect(m_secondSocket.data(), SIGNAL(readyRead()), this, SLOT(readSecondDataStream()));
   }
102

103
104
105
106
107
   m_localServer->close();
}

NodeInstanceServerProxy::~NodeInstanceServerProxy()
{
108
109
110
111
112
113
    if (m_firstSocket)
        m_firstSocket->close();

    if (m_secondSocket)
        m_secondSocket->close();

114

115
116
117
118
119
120
121
122
    if (m_qmlPuppetEditorProcess) {
        m_qmlPuppetEditorProcess->blockSignals(true);
        m_qmlPuppetEditorProcess->kill();
    }

    if (m_qmlPuppetPreviewProcess) {
        m_qmlPuppetPreviewProcess->blockSignals(true);
        m_qmlPuppetPreviewProcess->kill();
123
    }
124
125
126
127
128
129

    if (m_qmlPuppetEditorProcess && m_qmlPuppetEditorProcess->state() != QProcess::NotRunning)
        m_qmlPuppetEditorProcess->waitForFinished(1000);

    if (m_qmlPuppetPreviewProcess && m_qmlPuppetPreviewProcess->state() != QProcess::NotRunning)
        m_qmlPuppetPreviewProcess->waitForFinished(1000);
130
131
132
133
134
135
136
}

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");
137
    static const int childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
138
    static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
139
    static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
140
    static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
141
142
143
144
145
146
147

    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>());
148
149
    else if (command.userType() == childrenChangedCommandType)
        nodeInstanceClient()->childrenChanged(command.value<ChildrenChangedCommand>());
150
151
    else if (command.userType() == statePreviewImageChangedCommandType)
        nodeInstanceClient()->statePreviewImagesChanged(command.value<StatePreviewImageChangedCommand>());
152
153
    else if (command.userType() == componentCompletedCommandType)
        nodeInstanceClient()->componentCompleted(command.value<ComponentCompletedCommand>());
154
155
156
157
    else if (command.userType() == synchronizeCommandType) {
        SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
        m_synchronizeId = synchronizeCommand.synchronizeId();
    }  else
158
159
160
161
162
163
164
165
        Q_ASSERT(false);
}

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

166
static void writeCommandToSocket(const QVariant &command, QLocalSocket *socket)
167
{
168
169
170
171
172
173
174
175
176
177
    if(socket) {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out << quint32(0);
        out << command;
        out.device()->seek(0);
        out << quint32(block.size() - sizeof(quint32));

        socket->write(block);
    }
178
179
180
181
182
183
}

void NodeInstanceServerProxy::writeCommand(const QVariant &command)
{
    writeCommandToSocket(command, m_firstSocket.data());
    writeCommandToSocket(command, m_secondSocket.data());
184
185
186
187
188
189
190
191
192
193
194
195
196
197

    if (m_runModus == TestModus) {
        static int synchronizeId = 0;
        synchronizeId++;
        SynchronizeCommand synchronizeCommand(synchronizeId);

        writeCommandToSocket(QVariant::fromValue(synchronizeCommand), m_firstSocket.data());

        while(m_firstSocket->waitForReadyRead()) {
                readFirstDataStream();
                if (m_synchronizeId == synchronizeId)
                    return;
        }
    }
198
199
}

200
void NodeInstanceServerProxy::processFinished(int /*exitCode*/, QProcess::ExitStatus exitStatus)
201
{
202
203
204
205
    if (m_firstSocket)
        m_firstSocket->close();
    if (m_secondSocket)
        m_secondSocket->close();
206
207
    if (exitStatus == QProcess::CrashExit)
        emit processCrashed();
208
209
}

210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
void NodeInstanceServerProxy::readFirstDataStream()
{
    QList<QVariant> commandList;

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

        QDataStream in(m_firstSocket.data());

        if (m_firstBlockSize == 0) {
            in >> m_firstBlockSize;
        }

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

        QVariant command;
        in >> command;
        m_firstBlockSize = 0;

        commandList.append(command);
    }

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

void NodeInstanceServerProxy::readSecondDataStream()
241
242
243
{
    QList<QVariant> commandList;

244
245
    while (!m_secondSocket->atEnd()) {
        if (m_secondSocket->bytesAvailable() < int(sizeof(quint32)))
246
247
            break;

248
        QDataStream in(m_secondSocket.data());
249

250
251
        if (m_secondBlockSize == 0) {
            in >> m_secondBlockSize;
252
253
        }

254
        if (m_secondSocket->bytesAvailable() < m_secondBlockSize)
255
256
257
258
            break;

        QVariant command;
        in >> command;
259
        m_secondBlockSize = 0;
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323

        commandList.append(command);
    }

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

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));
}

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));
}

324
325
326
327
void NodeInstanceServerProxy::addImport(const AddImportCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}
328
329
330
331
332

void NodeInstanceServerProxy::completeComponent(const CompleteComponentCommand &command)
{
    writeCommand(QVariant::fromValue(command));
}
333
} // namespace QmlDesigner