~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/jabber_whiteboard/inkboard-document.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Inkscape::Whiteboard::InkboardDocument - Inkboard document implementation
 
3
 *
 
4
 * Authors:
 
5
 * David Yip <yipdw@rose-hulman.edu>
 
6
 *
 
7
 * Copyright (c) 2005 Authors
 
8
 *
 
9
 * Released under GNU GPL, read the file 'COPYING' for more information
 
10
 */
 
11
 
 
12
#include <glib.h>
 
13
#include <glibmm.h>
 
14
 
 
15
#include "jabber_whiteboard/inkboard-document.h"
 
16
 
 
17
#include "util/ucompose.hpp"
 
18
 
 
19
#include "jabber_whiteboard/message-utilities.h"
 
20
#include "jabber_whiteboard/defines.h"
 
21
#include "jabber_whiteboard/session-manager.h"
 
22
#include "jabber_whiteboard/node-tracker.h"
 
23
 
 
24
#include <glibmm.h>
 
25
#include <glib/gmessages.h>
 
26
#include <glib/gquark.h>
 
27
 
 
28
#include "jabber_whiteboard/inkboard-document.h"
 
29
#include "jabber_whiteboard/defines.h"
 
30
 
 
31
#include "xml/node.h"
 
32
#include "xml/event.h"
 
33
#include "xml/element-node.h"
 
34
#include "xml/text-node.h"
 
35
#include "xml/comment-node.h"
 
36
#include "xml/pi-node.h"
 
37
 
 
38
#include "util/share.h"
 
39
#include "util/ucompose.hpp"
 
40
 
 
41
namespace Inkscape {
 
42
 
 
43
namespace Whiteboard {
 
44
 
 
45
InkboardDocument::InkboardDocument(int code, State::SessionType sessionType,
 
46
                                   Glib::ustring const& to)
 
47
: XML::SimpleNode(code, this), sessionType(sessionType), recipient(to),
 
48
  _in_transaction(false)
 
49
{
 
50
    _initBindings();
 
51
}
 
52
 
 
53
void
 
54
InkboardDocument::_initBindings()
 
55
{
 
56
    this->sm = &SessionManager::instance();
 
57
    this->state = State::INITIAL;
 
58
    this->tracker = new KeyNodeTable();
 
59
}
 
60
 
 
61
void
 
62
InkboardDocument::setRecipient(Glib::ustring const& val)
 
63
{
 
64
    this->recipient = val;
 
65
}
 
66
 
 
67
Glib::ustring 
 
68
InkboardDocument::getRecipient() const
 
69
{
 
70
    return this->recipient;
 
71
}
 
72
 
 
73
void
 
74
InkboardDocument::setSessionId(Glib::ustring const& val)
 
75
{
 
76
    this->sessionId = val;
 
77
}
 
78
 
 
79
Glib::ustring 
 
80
InkboardDocument::getSessionId() const
 
81
{
 
82
    return this->sessionId;
 
83
}
 
84
 
 
85
void
 
86
InkboardDocument::startSessionNegotiation()
 
87
{
 
88
    if(this->sessionType == State::WHITEBOARD_PEER)
 
89
        this->send(recipient, Message::PROTOCOL,Message::CONNECT_REQUEST);
 
90
 
 
91
    else if(this->sessionType == State::WHITEBOARD_MUC)
 
92
    {
 
93
        // Check that the MUC room is whiteboard enabled, if not no need to send 
 
94
        // anything, just set the room to be whiteboard enabled
 
95
    }
 
96
}
 
97
 
 
98
void
 
99
InkboardDocument::terminateSession()
 
100
{
 
101
 
 
102
}
 
103
 
 
104
void
 
105
InkboardDocument::recieve(Message::Wrapper &wrapper, Pedro::Element* data)
 
106
{
 
107
    if(this->handleIncomingState(wrapper,data))
 
108
    {
 
109
        if(wrapper == Message::PROTOCOL)
 
110
        {
 
111
            Glib::ustring message = data->getFirstChild()->getFirstChild()->getFirstChild()->getName();
 
112
 
 
113
            if(message == Message::CONNECT_REQUEST)
 
114
            {
 
115
                // An MUC member requesting document
 
116
 
 
117
            }else if(message == Message::ACCEPT_INVITATION)
 
118
            {
 
119
                // TODO : Would be nice to create the desktop here
 
120
 
 
121
                this->send(getRecipient(),Message::PROTOCOL, Message::CONNECTED);
 
122
                this->send(getRecipient(),Message::PROTOCOL, Message::DOCUMENT_BEGIN);
 
123
 
 
124
                // Send Document
 
125
                this->sendDocument(this->root());
 
126
 
 
127
                this->send(getRecipient(),Message::PROTOCOL, Message::DOCUMENT_END);
 
128
 
 
129
            }else if(message == Message::DECLINE_INVITATION)
 
130
            {
 
131
                this->sm->terminateSession(this->getSessionId());
 
132
            }
 
133
        }else if(wrapper == Message::NEW || wrapper == Message::CONFIGURE
 
134
                    || wrapper == Message::MOVE || wrapper == Message::REMOVE )
 
135
        {
 
136
            handleChange(wrapper,data->getFirstChild()->getFirstChild());
 
137
        }
 
138
    }else{
 
139
        g_warning("Recieved Message in invalid state = %d", this->state);
 
140
        data->print();
 
141
    }
 
142
}
 
143
 
 
144
bool
 
145
InkboardDocument::send(const Glib::ustring &destJid, Message::Wrapper &wrapper, Message::Message &message)
 
146
{
 
147
    if(this->handleOutgoingState(wrapper,message))
 
148
    {
 
149
        Glib::ustring mes;
 
150
        if(wrapper == Message::PROTOCOL)
 
151
            mes = String::ucompose(Vars::PROTOCOL_MESSAGE,wrapper,message);
 
152
        else
 
153
            mes = message;
 
154
 
 
155
        char *finalmessage = const_cast<char* >(String::ucompose(
 
156
            Vars::WHITEBOARD_MESSAGE, this->sessionType, this->sm->getClient().getJid(),
 
157
            destJid, Vars::INKBOARD_XMLNS, this->getSessionId(), mes).c_str());
 
158
 
 
159
        if (!this->sm->getClient().write("%s",finalmessage)) 
 
160
            { return false; }
 
161
        else 
 
162
            { return true; }
 
163
 
 
164
    }else 
 
165
    { 
 
166
        g_warning("Sending Message in invalid state message=%s , state=%d",message.c_str(),this->state);
 
167
        return false; 
 
168
    }
 
169
}
 
170
 
 
171
void
 
172
InkboardDocument::sendDocument(Inkscape::XML::Node* root)
 
173
{
 
174
    for(Inkscape::XML::Node *child = root->firstChild();child!=NULL;child=child->next())
 
175
    {
 
176
        Glib::ustring name(child->name());
 
177
 
 
178
        if(name != "svg:metadata" && name != "svg:defs" && name != "sodipodi:namedview")
 
179
        {
 
180
            Glib::ustring parentKey,tempParentKey,key;
 
181
 
 
182
            this->addNodeToTracker(child);
 
183
            Message::Message message = this->composeNewMessage(child);
 
184
 
 
185
            this->send(this->getRecipient(),Message::NEW,message);
 
186
 
 
187
            if(child->childCount() != 0)
 
188
            {
 
189
                sendDocument(child);
 
190
            }
 
191
        }
 
192
    }
 
193
}
 
194
 
 
195
bool
 
196
InkboardDocument::handleOutgoingState(Message::Wrapper &wrapper, Glib::ustring const& message)
 
197
{
 
198
    if(wrapper == Message::PROTOCOL) 
 
199
    {
 
200
        if(message == Message::CONNECT_REQUEST) 
 
201
            return this->handleState(State::INITIAL,State::AWAITING_INVITATION_REPLY);
 
202
 
 
203
        else if(message == Message::ACCEPT_INVITATION)
 
204
            return this->handleState(State::CONNECTING,State::AWAITING_CONNECTED);
 
205
 
 
206
        else if(message == Message::CONNECTED)
 
207
            return this->handleState(State::INVITATION_RECIEVED,State::CONNECTED);
 
208
 
 
209
        else if(message == Message::DOCUMENT_BEGIN)
 
210
            return this->handleState(State::CONNECTED,State::SYNCHRONISING);
 
211
 
 
212
        else if(message == Message::DOCUMENT_END) { 
 
213
            return this->handleState(State::SYNCHRONISING,State::IN_WHITEBOARD);
 
214
        }
 
215
 
 
216
        else 
 
217
            return false;
 
218
 
 
219
    } else 
 
220
        if(this->state == State::SYNCHRONISING && wrapper == Message::NEW)
 
221
            return true;
 
222
 
 
223
    return this->state == State::IN_WHITEBOARD;
 
224
}
 
225
 
 
226
bool
 
227
InkboardDocument::handleIncomingState(Message::Wrapper &wrapper, Pedro::Element* data)
 
228
{
 
229
    if(wrapper == Message::PROTOCOL) 
 
230
    {
 
231
        Glib::ustring message = data->getFirstChild()->getFirstChild()->getFirstChild()->getName();
 
232
 
 
233
        if(message == Message::CONNECT_REQUEST)
 
234
            return this->handleState(State::INITIAL,State::CONNECTING);
 
235
        if(message == Message::ACCEPT_INVITATION)
 
236
            return this->handleState(State::AWAITING_INVITATION_REPLY,State::INVITATION_RECIEVED);
 
237
 
 
238
        else if(message == Message::CONNECTED)
 
239
            return this->handleState(State::AWAITING_CONNECTED,State::AWAITING_DOCUMENT_BEGIN);
 
240
 
 
241
        else if(message == Message::DOCUMENT_BEGIN)
 
242
            return this->handleState(State::AWAITING_DOCUMENT_BEGIN,State::SYNCHRONISING);
 
243
 
 
244
        else if(message == Message::DOCUMENT_END)
 
245
            return this->handleState(State::SYNCHRONISING,State::IN_WHITEBOARD);
 
246
 
 
247
        else 
 
248
            return false;
 
249
 
 
250
    } else 
 
251
        if(this->state == State::SYNCHRONISING && wrapper == Message::NEW)
 
252
            return true;
 
253
 
 
254
    return this->state == State::IN_WHITEBOARD;
 
255
}
 
256
 
 
257
bool 
 
258
InkboardDocument::handleState(State::SessionState expectedState, State::SessionState newState)
 
259
{
 
260
    if(this->state == expectedState)
 
261
    {
 
262
        this->state = newState;
 
263
        return true;
 
264
    }
 
265
 
 
266
    return false;
 
267
}
 
268
 
 
269
 
 
270
void
 
271
InkboardDocument::handleChange(Message::Wrapper &wrapper, Pedro::Element* data)
 
272
{
 
273
    if(wrapper == Message::NEW)
 
274
    {
 
275
        Glib::ustring parent =  data->getTagAttribute("new","parent");
 
276
        Glib::ustring id =      data->getTagAttribute("new","id");
 
277
 
 
278
        signed int index = atoi
 
279
            (data->getTagAttribute("new","index").c_str());
 
280
 
 
281
        Pedro::Element* element = data->getFirstChild();
 
282
 
 
283
        if(parent.size() > 0 && id.size() > 0)
 
284
            this->changeNew(parent,id,index,element);
 
285
 
 
286
    }else if(wrapper == Message::CONFIGURE)
 
287
    {
 
288
        if(data->exists("text"))
 
289
        {
 
290
            Glib::ustring text =    data->getFirstChild()->getValue();
 
291
            Glib::ustring target =  data->getTagAttribute("configure","target");
 
292
 
 
293
            unsigned int version = atoi
 
294
                (data->getTagAttribute("configure","version").c_str());
 
295
 
 
296
            if(text.size() > 0 && target.size() > 0)
 
297
                this->changeConfigureText(target,version,text);
 
298
 
 
299
        }else 
 
300
        {
 
301
            Glib::ustring target =      data->getTagAttribute("configure","target");
 
302
            Glib::ustring attribute =   data->getTagAttribute("configure","attribute");
 
303
            Glib::ustring value =       data->getTagAttribute("configure","value");
 
304
 
 
305
            unsigned int version = atoi
 
306
                (data->getTagAttribute("configure","version").c_str());
 
307
 
 
308
            if(target.size() > 0 && attribute.size() > 0 && value.size() > 0)
 
309
                this->changeConfigure(target,version,attribute,value);
 
310
        }
 
311
    }else if(wrapper == Message::MOVE)
 
312
    {
 
313
    }else if(wrapper == Message::REMOVE) 
 
314
    {
 
315
    }
 
316
}
 
317
 
 
318
void
 
319
InkboardDocument::beginTransaction()
 
320
{
 
321
    g_assert(!_in_transaction);
 
322
    _in_transaction = true;
 
323
}
 
324
 
 
325
void
 
326
InkboardDocument::rollback()
 
327
{
 
328
    g_assert(_in_transaction);
 
329
    _in_transaction = false;
 
330
}
 
331
 
 
332
void 
 
333
InkboardDocument::commit()
 
334
{
 
335
    g_assert(_in_transaction);
 
336
    _in_transaction = false;
 
337
}
 
338
 
 
339
XML::Event*
 
340
InkboardDocument::commitUndoable()
 
341
{
 
342
    g_assert(_in_transaction);
 
343
    _in_transaction = false;
 
344
    return NULL;
 
345
}
 
346
 
 
347
XML::Node*
 
348
InkboardDocument::createElement(char const* name)
 
349
{
 
350
    return new XML::ElementNode(g_quark_from_string(name), this);
 
351
}
 
352
 
 
353
XML::Node*
 
354
InkboardDocument::createTextNode(char const* content)
 
355
{
 
356
    return new XML::TextNode(Util::share_string(content), this);
 
357
}
 
358
 
 
359
XML::Node*
 
360
InkboardDocument::createComment(char const* content)
 
361
{
 
362
    return new XML::CommentNode(Util::share_string(content), this);
 
363
}
 
364
 
 
365
XML::Node*
 
366
InkboardDocument::createPI(char const *target, char const* content)
 
367
{
 
368
    return new XML::PINode(g_quark_from_string(target), Util::share_string(content), this);
 
369
}
 
370
 
 
371
 
 
372
 
 
373
void InkboardDocument::notifyChildAdded(XML::Node &/*parent*/,
 
374
                                        XML::Node &child,
 
375
                                        XML::Node */*prev*/)
 
376
{
 
377
    if (_in_transaction && state == State::IN_WHITEBOARD) {
 
378
 
 
379
        XML::Node *node = (XML::Node *)&child;
 
380
 
 
381
        if(tracker->get(node) == "")
 
382
        {
 
383
            addNodeToTracker(node);
 
384
            Message::Message message = composeNewMessage(node);
 
385
 
 
386
            send(getRecipient(),Message::NEW,message);
 
387
        }
 
388
    }
 
389
}
 
390
 
 
391
void InkboardDocument::notifyChildRemoved(XML::Node &/*parent*/,
 
392
                                          XML::Node &child,
 
393
                                          XML::Node */*prev*/)
 
394
{
 
395
    if (_in_transaction && state == State::IN_WHITEBOARD) 
 
396
    {
 
397
        XML::Node *element = (XML::Node *)&child;
 
398
 
 
399
        Message::Message message = String::ucompose(Vars::REMOVE_MESSAGE,
 
400
            tracker->get(element));
 
401
 
 
402
        send(getRecipient(),Message::REMOVE,message);
 
403
   }
 
404
}
 
405
 
 
406
void InkboardDocument::notifyChildOrderChanged(XML::Node &parent,
 
407
                                               XML::Node &child,
 
408
                                               XML::Node */*old_prev*/,
 
409
                                               XML::Node */*new_prev*/)
 
410
{
 
411
    if (_in_transaction && state == State::IN_WHITEBOARD) 
 
412
    {
 
413
        unsigned int index = child.position();
 
414
 
 
415
        Message::Message message = String::ucompose(Vars::MOVE_MESSAGE,
 
416
                tracker->get(&child),index);
 
417
 
 
418
        send(getRecipient(),Message::MOVE,message);
 
419
    }
 
420
}
 
421
 
 
422
void InkboardDocument::notifyContentChanged(XML::Node &node,
 
423
                                            Util::ptr_shared<char> /*old_content*/,
 
424
                                            Util::ptr_shared<char> new_content)
 
425
{
 
426
    if (_in_transaction && state == State::IN_WHITEBOARD) 
 
427
    {
 
428
        XML::Node *element = (XML::Node *)&node;
 
429
 
 
430
        Glib::ustring value(new_content.pointer());
 
431
 
 
432
        Glib::ustring change = tracker->getLastHistory(element,"text");
 
433
 
 
434
        if(change.size() > 0 && change == value)
 
435
            return;
 
436
 
 
437
        if(new_content.pointer())
 
438
        {
 
439
            unsigned int version = tracker->incrementVersion(element);
 
440
 
 
441
            Message::Message message = String::ucompose(Vars::CONFIGURE_TEXT_MESSAGE,
 
442
                tracker->get(element),version,new_content.pointer());
 
443
 
 
444
            send(getRecipient(),Message::CONFIGURE,message);
 
445
        }
 
446
    }
 
447
}
 
448
 
 
449
void InkboardDocument::notifyAttributeChanged(XML::Node &node,
 
450
                                              GQuark name,
 
451
                                              Util::ptr_shared<char> /*old_value*/,
 
452
                                              Util::ptr_shared<char> new_value)
 
453
{
 
454
    if (_in_transaction && state == State::IN_WHITEBOARD) 
 
455
    {
 
456
        XML::Node *element = (XML::Node *)&node;
 
457
 
 
458
        Glib::ustring value(new_value.pointer());
 
459
        Glib::ustring attribute(g_quark_to_string(name));
 
460
 
 
461
        Glib::ustring change = tracker->getLastHistory(element,attribute);
 
462
 
 
463
        if(change.size() > 0 && change == value)
 
464
            return;
 
465
 
 
466
        if(attribute.size() > 0 && value.size() > 0)
 
467
        {
 
468
            unsigned int version = tracker->incrementVersion(element);
 
469
 
 
470
            Message::Message message = String::ucompose(Vars::CONFIGURE_MESSAGE,
 
471
                tracker->get(element),version,attribute.c_str(),value.c_str());
 
472
 
 
473
            send(getRecipient(),Message::CONFIGURE,message);
 
474
        }
 
475
    }
 
476
}
 
477
 
 
478
}
 
479
 
 
480
}