File indexing completed on 2024-05-05 05:40:40

0001 /***************************************************************************
0002  *  Copyright (C) 2019 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "worker/messagehelper.h"
0021 
0022 #include <QBuffer>
0023 #include <QDebug>
0024 #include <QJsonDocument>
0025 #include <QJsonObject>
0026 #include <QRgb>
0027 
0028 #include "controller/view_controller/charactersheetcontroller.h"
0029 #include "controller/view_controller/imagecontroller.h"
0030 #include "controller/view_controller/mediacontrollerbase.h"
0031 #include "controller/view_controller/mindmapcontroller.h"
0032 #include "controller/view_controller/pdfcontroller.h"
0033 #include "controller/view_controller/sharednotecontroller.h"
0034 #include "controller/view_controller/vectorialmapcontroller.h"
0035 #include "controller/view_controller/webpagecontroller.h"
0036 
0037 #include "controller/item_controllers/characteritemcontroller.h"
0038 #include "controller/item_controllers/ellipsecontroller.h"
0039 #include "controller/item_controllers/gridcontroller.h"
0040 #include "controller/item_controllers/imageitemcontroller.h"
0041 #include "controller/item_controllers/linecontroller.h"
0042 #include "controller/item_controllers/pathcontroller.h"
0043 #include "controller/item_controllers/rectcontroller.h"
0044 #include "controller/item_controllers/sightcontroller.h"
0045 #include "controller/item_controllers/textcontroller.h"
0046 #include "controller/item_controllers/visualitemcontroller.h"
0047 
0048 #include "charactersheet/charactersheet.h"
0049 #include "charactersheet/charactersheetmodel.h"
0050 #include "charactersheet/imagemodel.h"
0051 #include "charactersheet/worker/ioworker.h"
0052 #include "data/character.h"
0053 #include "data/player.h"
0054 #include "diceparser/dicealias.h"
0055 #include "mindmap/data/linkcontroller.h"
0056 #include "mindmap/data/mindnode.h"
0057 #include "mindmap/model/minditemmodel.h"
0058 
0059 #include "mindmap/data/packagenode.h"
0060 #include "mindmap/model/linkmodel.h"
0061 #include "model/characterstatemodel.h"
0062 #include "model/dicealiasmodel.h"
0063 #include "model/playermodel.h"
0064 #include "model/vmapitemmodel.h"
0065 #include "network/networkmessagereader.h"
0066 #include "network/networkmessagewriter.h"
0067 
0068 #include "worker/iohelper.h"
0069 #include "worker/playermessagehelper.h"
0070 
0071 QByteArray imageToByteArray(const QImage& img)
0072 {
0073     QByteArray array;
0074     QBuffer buffer(&array);
0075     img.save(&buffer, "PNG");
0076     return array;
0077 }
0078 
0079 void MessageHelper::sendOffGoodBye()
0080 {
0081     NetworkMessageWriter message(NetMsg::AdministrationCategory, NetMsg::Goodbye);
0082     message.sendToServer();
0083 }
0084 
0085 QString MessageHelper::readPlayerId(NetworkMessageReader& msg)
0086 {
0087     return msg.string8();
0088 }
0089 
0090 void MessageHelper::sendOffAllDiceAlias(DiceAliasModel* model)
0091 {
0092     if(nullptr == model)
0093         return;
0094 
0095     auto const& aliases= model->aliases();
0096     int i= 0;
0097     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::DiceAliasModel);
0098     msg.uint32(static_cast<quint32>(aliases.size()));
0099     for(auto const& alias : aliases)
0100     {
0101         msg.int64(i);
0102         msg.string32(alias->pattern());
0103         msg.string32(alias->command());
0104         msg.int8(alias->isReplace());
0105         msg.int8(alias->isEnable());
0106         msg.string32(alias->comment());
0107         ++i;
0108     }
0109     msg.sendToServer();
0110 }
0111 
0112 void MessageHelper::sendOffDiceAliasRemoved(int i)
0113 {
0114     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::removeDiceAlias);
0115     msg.int64(i);
0116     msg.sendToServer();
0117 }
0118 void MessageHelper::sendOffDiceAliasMoved(int i, int j)
0119 {
0120     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::moveDiceAlias);
0121     msg.int64(i);
0122     msg.int64(j);
0123     msg.sendToServer();
0124 }
0125 
0126 void MessageHelper::sendOffOneDiceAlias(const DiceAlias* da, int row)
0127 {
0128     if(nullptr == da)
0129         return;
0130 
0131     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::addDiceAlias);
0132     msg.int64(row);
0133     msg.string32(da->pattern());
0134     msg.string32(da->command());
0135     msg.int8(da->isReplace());
0136     msg.int8(da->isEnable());
0137     msg.string32(da->comment());
0138     msg.sendToServer();
0139 }
0140 
0141 void MessageHelper::sendOffCharacterStateRemoved(const QString& id)
0142 {
0143     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::removeCharacterState);
0144     msg.string8(id);
0145     msg.sendToServer();
0146 }
0147 
0148 void MessageHelper::sendOffCharacterStateMoved(int i, int j)
0149 {
0150     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::moveCharacterState);
0151     msg.int64(i);
0152     msg.int64(j);
0153     msg.sendToServer();
0154 }
0155 
0156 void MessageHelper::sendOffAllCharacterState(CharacterStateModel* model)
0157 {
0158     if(nullptr == model)
0159         return;
0160 
0161     auto const& states= model->statesList();
0162     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::CharactereStateModel);
0163     msg.uint32(static_cast<quint32>(states.size()));
0164     for(auto const& state : states)
0165     {
0166         msg.string32(state->label());
0167         msg.rgb(state->color().rgb());
0168         msg.pixmap(state->pixmap());
0169     }
0170     msg.sendToServer();
0171 }
0172 
0173 void MessageHelper::sendOffOneCharacterState(const CharacterState* state, int row)
0174 {
0175     if(nullptr == state)
0176         return;
0177 
0178     NetworkMessageWriter msg(NetMsg::CampaignCategory, NetMsg::addCharacterState);
0179     msg.int64(row);
0180     msg.string32(state->label());
0181     msg.rgb(state->color().rgb());
0182     msg.pixmap(state->pixmap());
0183     msg.sendToServer();
0184 }
0185 
0186 QString MessageHelper::readMediaId(NetworkMessageReader* msg)
0187 {
0188     return msg->string8();
0189 }
0190 
0191 QHash<QString, QVariant> MessageHelper::readMediaData(NetworkMessageReader* msg)
0192 {
0193     auto uuid= msg->string8();
0194     auto name= msg->string32();
0195     auto contentType= msg->uint8();
0196     auto ownerId= msg->string32();
0197 
0198     return {{"uuid", uuid}, {"name", name}, {"contentType", contentType}, {"ownerId", ownerId}};
0199 }
0200 
0201 void MessageHelper::sendOffMediaControllerBase(const MediaControllerBase* ctrl, NetworkMessageWriter& msg)
0202 {
0203     msg.string8(ctrl->uuid());
0204     msg.string32(ctrl->name());
0205     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0206     msg.string32(ctrl->ownerId());
0207 }
0208 
0209 void MessageHelper::closeMedia(const QString& id, Core::ContentType type)
0210 {
0211     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::CloseMedia);
0212     msg.uint8(static_cast<quint8>(type));
0213     msg.string8(id);
0214     msg.sendToServer();
0215 }
0216 
0217 void MessageHelper::sendOffImage(ImageController* ctrl)
0218 {
0219     if(nullptr == ctrl)
0220         return;
0221 
0222     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
0223     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0224     sendOffMediaControllerBase(ctrl, msg);
0225     msg.byteArray32(ctrl->data());
0226 
0227     msg.sendToServer();
0228 }
0229 
0230 QHash<QString, QVariant> MessageHelper::readImageData(NetworkMessageReader* msg)
0231 {
0232     auto hash= readMediaData(msg);
0233     auto data= msg->byteArray32();
0234     hash.insert(Core::keys::KEY_DATA, data);
0235     return hash;
0236 }
0237 
0238 void MessageHelper::updatePerson(NetworkMessageReader& data, PlayerModel* playerModel)
0239 {
0240     QString uuid= data.string8();
0241     auto property= data.string16();
0242     bool isCharacter= data.action() == NetMsg::ChangeCharacterPropertyAct;
0243 
0244     Person* person{nullptr};
0245 
0246     int role= -1;
0247 
0248     if(isCharacter)
0249         person= playerModel->characterById(uuid);
0250     else
0251         person= playerModel->playerById(uuid);
0252 
0253     if(nullptr == person)
0254         return;
0255 
0256     QVariant var;
0257     if(property == Core::person::name)
0258     {
0259         role= PlayerModel::NameRole;
0260         var= QVariant::fromValue(data.string32());
0261     }
0262     else if(property == Core::person::color)
0263     {
0264         role= PlayerModel::ColorRole;
0265         var= QVariant::fromValue(QColor(data.rgb()));
0266     }
0267     else if(property == Core::person::avatar)
0268     {
0269         var= QVariant::fromValue(data.byteArray32());
0270     }
0271     else if(property == Core::person::stateId)
0272     {
0273         var= QVariant::fromValue(data.string32());
0274     }
0275     else if(property == Core::person::healthPoints)
0276     {
0277         var= QVariant::fromValue(data.int64());
0278     }
0279     else if(property == Core::person::isNpc)
0280     {
0281         var= QVariant::fromValue(static_cast<bool>(data.uint8()));
0282     }
0283     else if(property == Core::person::maxHP)
0284     {
0285         var= QVariant::fromValue(data.int64());
0286     }
0287     else if(property == Core::person::minHP)
0288     {
0289         var= QVariant::fromValue(data.int64());
0290     }
0291     else if(property == Core::person::distancePerTurn)
0292     {
0293         var= QVariant::fromValue(data.int64());
0294     }
0295     else if(property == Core::person::initCommand)
0296     {
0297         var= QVariant::fromValue(data.string32());
0298     }
0299     else if(property == Core::person::initiative)
0300     {
0301         var= QVariant::fromValue(data.int64());
0302     }
0303     else if(property == Core::person::hasInitiative)
0304     {
0305         var= QVariant::fromValue(static_cast<bool>(data.uint8()));
0306     }
0307     else if(property == Core::person::lifeColor)
0308     {
0309         var= QVariant::fromValue(QColor(data.rgb()));
0310     }
0311 
0312     // set value
0313     if(role != -1)
0314     {
0315         auto idx= playerModel->personToIndex(person);
0316         playerModel->setData(idx, var, role);
0317     }
0318     else
0319     {
0320         person->setProperty(property.toLocal8Bit(), var);
0321     }
0322 }
0323 
0324 void MessageHelper::stopSharingSheet(const QString& sheetId, const QString& ctrlId, const QString& characterId)
0325 {
0326     NetworkMessageWriter msg(NetMsg::CharacterSheetCategory, NetMsg::closeCharacterSheet);
0327     msg.string8(sheetId);
0328     msg.string8(ctrlId);
0329     msg.string8(characterId);
0330     msg.sendToServer();
0331 }
0332 
0333 void MessageHelper::shareCharacterSheet(CharacterSheet* sheet, Character* character, CharacterSheetController* ctrl)
0334 {
0335     if(sheet == nullptr || character == nullptr)
0336         return;
0337 
0338     Player* parent= character->getParentPlayer();
0339 
0340     if(parent == nullptr)
0341         return;
0342 
0343     NetworkMessageWriter msg(NetMsg::CharacterSheetCategory, NetMsg::addCharacterSheet);
0344     QStringList idList;
0345     idList << parent->uuid();
0346     msg.setRecipientList(idList, NetworkMessage::OneOrMany);
0347     // msg.string8(parent->uuid());
0348 
0349     msg.string8(ctrl->uuid());
0350     msg.string8(ctrl->name());
0351     msg.string8(character->uuid());
0352 
0353     QJsonObject object;
0354     sheet->save(object);
0355     QJsonDocument doc;
0356     doc.setObject(object);
0357     msg.byteArray32(doc.toJson());
0358 
0359     msg.string32(ctrl->qmlCode());
0360 
0361     auto imageModel= ctrl->imageModel();
0362     QJsonArray array= IOWorker::saveImageModel(imageModel);
0363     // imageModel->save(array);
0364     QJsonDocument doc2;
0365     doc2.setArray(array);
0366     msg.byteArray32(doc2.toJson());
0367 
0368     auto model= ctrl->model();
0369     QJsonDocument doc3;
0370     // doc3.setObject(model->rootSectionData());
0371     msg.byteArray32(doc3.toJson());
0372 
0373     msg.sendToServer();
0374 }
0375 
0376 QHash<QString, QVariant> MessageHelper::readCharacterSheet(NetworkMessageReader* msg)
0377 {
0378     if(nullptr == msg)
0379         return {};
0380 
0381     auto hash= readMediaData(msg);
0382     auto id= msg->string8();
0383     auto name= msg->string8();
0384     auto characterId= msg->string8();
0385     auto data= msg->byteArray32();
0386     auto qml= msg->string32();
0387     auto imageData= msg->byteArray32();
0388     auto rootSection= msg->byteArray32();
0389 
0390     hash.insert(Core::keys::KEY_ID, id);
0391     hash.insert(Core::keys::KEY_NAME, name);
0392     hash.insert(Core::keys::KEY_CHARACTERID, characterId);
0393     hash.insert(Core::keys::KEY_DATA, data);
0394     hash.insert(Core::keys::KEY_QML, qml);
0395     hash.insert(Core::keys::KEY_IMAGEDATA, imageData);
0396     hash.insert(Core::keys::KEY_ROOTSECTION, rootSection);
0397 
0398     return hash;
0399 }
0400 
0401 void MessageHelper::readUpdateField(CharacterSheetController* ctrl, NetworkMessageReader* msg)
0402 {
0403     if(nullptr == ctrl || nullptr == msg)
0404         return;
0405 
0406     auto sheetId= msg->string8();
0407     auto path= msg->string32();
0408     auto data= msg->byteArray32();
0409 
0410     QJsonDocument doc= QJsonDocument::fromJson(data);
0411     auto obj= doc.object();
0412     ctrl->updateFieldFrom(sheetId, obj, data);
0413 }
0414 
0415 // mindmap
0416 void fillUpMessageWithMindmap(NetworkMessageWriter& msg, MindMapController* ctrl)
0417 {
0418     if(ctrl == nullptr)
0419         return;
0420 
0421     msg.string8(ctrl->uuid());
0422     msg.uint8(ctrl->sharingToAll() == Core::SharingPermission::ReadWrite);
0423     msg.uint64(ctrl->defaultStyleIndex());
0424 
0425     auto nodeModel= dynamic_cast<mindmap::MindItemModel*>(ctrl->itemModel());
0426     auto imageModel= ctrl->imgModel();
0427 
0428     auto nodes= nodeModel->items(mindmap::MindItem::Type::NodeType);
0429 
0430     msg.uint64(static_cast<quint64>(nodes.size()));
0431     for(auto i : nodes)
0432     {
0433         auto node= dynamic_cast<mindmap::MindNode*>(i);
0434 
0435         if(!node)
0436             continue;
0437 
0438         msg.string8(node->id());
0439         msg.string8(node->parentId());
0440         msg.string32(node->text());
0441         msg.uint64(node->styleIndex());
0442         msg.real(node->position().x());
0443         msg.real(node->position().y());
0444         msg.string16(node->imageUri());
0445     }
0446 
0447     auto const& links= nodeModel->items(mindmap::MindItem::Type::LinkType);
0448     msg.uint64(links.size());
0449     for(auto i : links)
0450     {
0451         auto link= dynamic_cast<mindmap::LinkController*>(i);
0452 
0453         if(!link)
0454             continue;
0455 
0456         msg.string8(link->id());
0457         msg.uint8(static_cast<quint8>(link->direction()));
0458         msg.string8(link->start()->id());
0459         auto end= link->end();
0460         msg.string8(end ? end->id() : QString());
0461         msg.string16(link->text());
0462     }
0463 
0464     auto packs= nodeModel->items(mindmap::MindItem::Type::PackageType);
0465 
0466     msg.uint64(packs.size());
0467     for(auto const& i : packs)
0468     {
0469         auto pack= dynamic_cast<mindmap::PackageNode*>(i);
0470         if(!pack)
0471             continue;
0472 
0473         msg.string8(pack->id());
0474         msg.string16(pack->title());
0475         auto const& children= pack->children();
0476         msg.uint32(children.size());
0477         for(auto const& c : children)
0478         {
0479             msg.string8(c->id());
0480         }
0481     }
0482 
0483     auto imageInfos= imageModel->imageInfos();
0484     msg.uint64(imageInfos.size());
0485     for(auto const& image : imageInfos)
0486     {
0487         msg.byteArray32(IOHelper::pixmapToData(image.m_pixmap));
0488         msg.string8(image.m_id);
0489         msg.string16(image.m_url.toString());
0490     }
0491 }
0492 
0493 void MessageHelper::sendOffMindmapToAll(MindMapController* ctrl)
0494 {
0495     if(nullptr == ctrl || !ctrl->localIsOwner())
0496         return;
0497 
0498     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
0499     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0500     sendOffMediaControllerBase(ctrl, msg);
0501     fillUpMessageWithMindmap(msg, ctrl);
0502     msg.sendToServer();
0503 }
0504 
0505 void MessageHelper::sendOffMindmapPermissionUpdate(MindMapController* ctrl)
0506 {
0507     NetworkMessageWriter msg(NetMsg::MindMapCategory, NetMsg::UpdateMindMapPermission);
0508     msg.string8(ctrl->uuid());
0509     msg.uint8(ctrl->sharingToAll() == Core::SharingPermission::ReadWrite);
0510     msg.sendToServer();
0511 }
0512 
0513 void MessageHelper::sendOffMindmapPermissionUpdateTo(Core::SharingPermission perm, MindMapController* ctrl,
0514                                                      const QString& id)
0515 {
0516     QStringList list;
0517     list << id;
0518     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::UpdateMindMapPermission);
0519     msg.setRecipientList(list, NetworkMessage::OneOrMany);
0520     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0521     msg.string8(ctrl->uuid());
0522     msg.uint8(perm == Core::SharingPermission::ReadWrite);
0523     msg.sendToServer();
0524 }
0525 
0526 void MessageHelper::openMindmapTo(MindMapController* ctrl, const QString& id)
0527 {
0528     if(nullptr == ctrl)
0529         return;
0530 
0531     QStringList recipiants;
0532     recipiants << id;
0533 
0534     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
0535     msg.setRecipientList(recipiants, NetworkMessage::OneOrMany);
0536     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0537     sendOffMediaControllerBase(ctrl, msg);
0538     fillUpMessageWithMindmap(msg, ctrl);
0539     msg.sendToServer();
0540 }
0541 
0542 void MessageHelper::closeMindmapTo(MindMapController* ctrl, const QString& id)
0543 {
0544     if(nullptr == ctrl)
0545         return;
0546 
0547     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::CloseMedia);
0548     msg.setRecipientList({id}, NetworkMessage::OneOrMany);
0549     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0550     msg.string8(ctrl->uuid());
0551     msg.sendToServer();
0552 }
0553 
0554 QHash<QString, QVariant> MessageHelper::readMindMap(NetworkMessageReader* msg)
0555 {
0556     if(nullptr == msg)
0557         return {};
0558 
0559     auto hash= readMediaData(msg);
0560 
0561     hash["uuid"]= msg->string8();
0562     hash["readwrite"]= msg->uint8();
0563     hash["indexStyle"]= msg->uint64();
0564 
0565     QHash<QString, QVariant> nodes;
0566 
0567     auto size= msg->uint64();
0568 
0569     for(quint64 i= 0; i < size; ++i)
0570     {
0571         QHash<QString, QVariant> node;
0572         node["uuid"]= msg->string8();
0573         node["parentId"]= msg->string8();
0574         node["text"]= msg->string32();
0575         node["index"]= msg->uint64();
0576         node["x"]= msg->real();
0577         node["y"]= msg->real();
0578         node["imageUri"]= msg->string16();
0579 
0580         nodes.insert(QString("node_%1").arg(i), node);
0581     }
0582 
0583     hash["nodes"]= nodes;
0584 
0585     QHash<QString, QVariant> links;
0586     size= msg->uint64();
0587 
0588     for(quint64 i= 0; i < size; ++i)
0589     {
0590         QHash<QString, QVariant> link;
0591         link["uuid"]= msg->string8();
0592         link["direction"]= msg->uint8();
0593         link["startId"]= msg->string8();
0594         link["endId"]= msg->string8();
0595         link["text"]= msg->string16();
0596         links.insert(QString("link_%1").arg(i), link);
0597     }
0598     hash["links"]= links;
0599 
0600     QHash<QString, QVariant> packages;
0601     size= msg->uint64();
0602 
0603     for(quint64 i= 0; i < size; ++i)
0604     {
0605         QHash<QString, QVariant> pack;
0606         pack["uuid"]= msg->string8();
0607         pack["title"]= msg->string16();
0608         auto childrenCount= msg->uint32();
0609         QStringList childrenId;
0610         for(unsigned int i= 0; i < childrenCount; ++i)
0611         {
0612             childrenId.append(msg->string8());
0613         }
0614         pack["children"]= childrenId;
0615         packages.insert(QString("pack_%1").arg(i), pack);
0616     }
0617     hash["packages"]= packages;
0618 
0619     QHash<QString, QVariant> imageInfoData;
0620     size= msg->uint64();
0621     for(quint64 i= 0; i < size; ++i)
0622     {
0623         QHash<QString, QVariant> imgInfo;
0624         imgInfo["pixmap"]= IOHelper::dataToPixmap(msg->byteArray32());
0625         imgInfo["id"]= msg->string8();
0626         imgInfo["url"]= QUrl(msg->string16());
0627         imageInfoData.insert(QString("img_%1").arg(i), imgInfo);
0628     }
0629     hash["imageInfoData"]= imageInfoData;
0630 
0631     return hash;
0632 }
0633 // end - mindmap
0634 
0635 // Shared Notes
0636 void MessageHelper::closeNoteTo(SharedNoteController* sharedCtrl, const QString& id)
0637 {
0638     if(nullptr == sharedCtrl)
0639         return;
0640 
0641     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::CloseMedia);
0642     msg.setRecipientList({id}, NetworkMessage::OneOrMany);
0643     msg.uint8(static_cast<quint8>(sharedCtrl->contentType()));
0644     msg.string8(sharedCtrl->uuid());
0645     msg.sendToServer();
0646 }
0647 
0648 void MessageHelper::shareNotesTo(const SharedNoteController* ctrl, const QStringList& recipiants)
0649 {
0650     if(nullptr == ctrl)
0651         return;
0652 
0653     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
0654     msg.setRecipientList(recipiants, NetworkMessage::OneOrMany);
0655     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0656     sendOffMediaControllerBase(ctrl, msg);
0657     msg.uint8(static_cast<bool>(ctrl->highligthedSyntax() == SharedNoteController::HighlightedSyntax::MarkDown));
0658     msg.string32(ctrl->text());
0659     msg.sendToServer();
0660 }
0661 QHash<QString, QVariant> MessageHelper::readSharedNoteData(NetworkMessageReader* msg)
0662 {
0663     if(nullptr == msg)
0664         return {};
0665 
0666     auto hash= readMediaData(msg);
0667     auto mkH= static_cast<bool>(msg->uint8());
0668     auto text= msg->string32();
0669 
0670     hash.insert(Core::vmapkeys::KEY_MARKDOWN, mkH);
0671     hash.insert(Core::vmapkeys::KEY_TEXT, text);
0672 
0673     return hash;
0674 }
0675 // End - Shared Notes
0676 
0677 // Webpage
0678 QHash<QString, QVariant> MessageHelper::readWebPageData(NetworkMessageReader* msg)
0679 {
0680     if(nullptr == msg)
0681         return {};
0682 
0683     auto hash= readMediaData(msg);
0684 
0685     auto mode= msg->uint8();
0686     auto data= msg->string32();
0687 
0688     hash.insert(Core::keys::KEY_MODE, mode);
0689     hash.insert(Core::keys::KEY_DATA, data);
0690     hash.insert(Core::keys::KEY_STATE, static_cast<int>(WebpageController::RemoteView));
0691 
0692     return hash;
0693 }
0694 
0695 void MessageHelper::shareWebpage(WebpageController* ctrl)
0696 {
0697     if(nullptr == ctrl)
0698         return;
0699 
0700     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
0701     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0702     sendOffMediaControllerBase(ctrl, msg);
0703     auto mode= ctrl->sharingMode();
0704     msg.uint8(mode);
0705     if(mode == WebpageController::Html)
0706         msg.string32(ctrl->html());
0707     else if(mode == WebpageController::Url)
0708         msg.string32(ctrl->url().toString());
0709     msg.sendToServer();
0710 }
0711 
0712 void MessageHelper::updateWebpage(WebpageController* ctrl)
0713 {
0714     if(nullptr == ctrl)
0715         return;
0716 
0717     auto mode= ctrl->sharingMode();
0718     if(mode == WebpageController::None)
0719         return;
0720 
0721     NetworkMessageWriter msg(NetMsg::WebPageCategory, NetMsg::UpdateContent);
0722     msg.string8(ctrl->uuid());
0723     msg.uint8(mode);
0724     if(mode == WebpageController::Html)
0725         msg.string32(ctrl->html());
0726     else if(mode == WebpageController::Url)
0727         msg.string32(ctrl->url().toString());
0728 
0729     msg.sendToServer();
0730 }
0731 
0732 void MessageHelper::readUpdateWebpage(WebpageController* ctrl, NetworkMessageReader* msg)
0733 {
0734     qDebug() << "readUpdateWebpage WebPage NetworkMessageReader";
0735     if(msg == nullptr || nullptr == ctrl)
0736         return;
0737 
0738     auto mode= static_cast<WebpageController::SharingMode>(msg->uint8());
0739     auto data= msg->string32();
0740 
0741     if(mode == WebpageController::Html)
0742         ctrl->setHtml(data);
0743     else if(mode == WebpageController::Url)
0744         ctrl->setUrl(QUrl::fromUserInput(data));
0745 }
0746 // end - Webpage
0747 
0748 void MessageHelper::sendOffPdfFile(PdfController* ctrl)
0749 {
0750     if(nullptr == ctrl)
0751         return;
0752 
0753     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
0754     msg.uint8(static_cast<quint8>(ctrl->contentType()));
0755     msg.string8(ctrl->uuid());
0756     msg.byteArray32(ctrl->data());
0757     msg.sendToServer();
0758 }
0759 
0760 QHash<QString, QVariant> MessageHelper::readPdfData(NetworkMessageReader* msg)
0761 {
0762     if(nullptr == msg)
0763         return {};
0764 
0765     auto id= msg->string8();
0766     auto data= msg->byteArray32();
0767 
0768     return QHash<QString, QVariant>({{Core::keys::KEY_ID, id}, {Core::keys::KEY_DATA, data}});
0769 }
0770 
0771 void addVisualItemController(const vmap::VisualItemController* ctrl, NetworkMessageWriter& msg)
0772 {
0773     msg.uint8(ctrl->itemType());
0774     msg.uint8(ctrl->visible());
0775     msg.uint8(ctrl->initialized());
0776     msg.real(ctrl->opacity());
0777     msg.real(ctrl->rotation());
0778     msg.uint8(static_cast<quint8>(ctrl->layer()));
0779     auto pos= ctrl->pos();
0780     msg.real(pos.x());
0781     msg.real(pos.y());
0782     msg.string8(ctrl->uuid());
0783     msg.rgb(ctrl->color().rgb());
0784     msg.uint8(ctrl->locked());
0785 }
0786 
0787 const std::map<QString, QVariant> readVisualItemController(NetworkMessageReader* msg)
0788 {
0789     auto itemtype= msg->uint8();
0790     auto visible= msg->uint8();
0791     auto initialized= msg->uint8();
0792     auto opacity= msg->real();
0793     auto rotation= msg->real();
0794     auto layer= msg->uint8();
0795     QPointF pos;
0796     pos.setX(msg->real());
0797     pos.setY(msg->real());
0798     auto uuid= msg->string8();
0799     auto rgb= QColor(msg->rgb());
0800     auto locked= msg->uint8();
0801 
0802     return std::map<QString, QVariant>({{Core::vmapkeys::KEY_VISIBLE, visible},
0803                                         {Core::vmapkeys::KEY_INITIALIZED, initialized},
0804                                         {Core::vmapkeys::KEY_OPACITY, opacity},
0805                                         {Core::vmapkeys::KEY_ROTATION, rotation},
0806                                         {Core::vmapkeys::KEY_LAYER, layer},
0807                                         {Core::vmapkeys::KEY_POS, pos},
0808                                         {Core::vmapkeys::KEY_ITEMTYPE, itemtype},
0809                                         {Core::vmapkeys::KEY_UUID, uuid},
0810                                         {Core::vmapkeys::KEY_COLOR, rgb},
0811                                         {Core::vmapkeys::KEY_LOCKED, locked}});
0812 }
0813 
0814 QHash<QString, QVariant> readSightController(NetworkMessageReader* msg)
0815 {
0816     if(nullptr == msg)
0817         return {};
0818 
0819     QHash<QString, QVariant> hash;
0820 
0821     hash[Core::vmapkeys::KEY_UUID]= msg->string8();
0822     hash[Core::vmapkeys::KEY_SIGHT_X]= msg->real();
0823     hash[Core::vmapkeys::KEY_SIGHT_Y]= msg->real();
0824     hash[Core::vmapkeys::KEY_SIGHT_W]= msg->real();
0825     hash[Core::vmapkeys::KEY_SIGHT_H]= msg->real();
0826     hash[Core::vmapkeys::KEY_SIGHT_POSX]= msg->real();
0827     hash[Core::vmapkeys::KEY_SIGHT_POSY]= msg->real();
0828 
0829     auto data= msg->byteArray32();
0830 
0831     QDataStream read(data);
0832     QPainterPath path;
0833     read >> path;
0834 
0835     hash[Core::vmapkeys::KEY_SIGHT_PATH]= QVariant::fromValue(path);
0836 
0837     return hash;
0838 }
0839 
0840 void addSightController(vmap::SightController* ctrl, NetworkMessageWriter& msg)
0841 {
0842     if(nullptr == ctrl)
0843         return;
0844 
0845     msg.string8(ctrl->uuid());
0846     auto rect= ctrl->rect();
0847     msg.real(rect.x());
0848     msg.real(rect.y());
0849     msg.real(rect.width());
0850     msg.real(rect.height());
0851 
0852     auto pos= ctrl->pos();
0853     msg.real(pos.x());
0854     msg.real(pos.y());
0855 
0856     auto path= ctrl->fowPath();
0857     QByteArray array;
0858     {
0859         QDataStream write(&array, QIODevice::WriteOnly);
0860         write << path;
0861     }
0862     msg.byteArray32(array);
0863 
0864     /*auto singularity= ctrl->singularityList();
0865     msg.uint64(static_cast<quint64>(singularity.size()));
0866     for(auto const& pair : qAsConst(singularity))
0867     {
0868         auto points= pair.first;
0869         msg.uint64(static_cast<quint64>(points.size()));
0870         msg.uint8(static_cast<quint8>(pair.second));
0871 
0872         std::for_each(points.begin(), points.end(),
0873                       [&msg](const QPointF& p)
0874                       {
0875                           msg.real(p.x());
0876                           msg.real(p.y());
0877                       });
0878     }*/
0879 }
0880 
0881 void addRectController(const vmap::RectController* ctrl, NetworkMessageWriter& msg)
0882 {
0883     addVisualItemController(ctrl, msg);
0884     msg.uint8(ctrl->filled());
0885     msg.uint16(ctrl->penWidth());
0886     auto rect= ctrl->rect();
0887     msg.real(rect.x());
0888     msg.real(rect.y());
0889     msg.real(rect.width());
0890     msg.real(rect.height());
0891 }
0892 
0893 const std::map<QString, QVariant> MessageHelper::readRect(NetworkMessageReader* msg)
0894 {
0895     auto hash= readVisualItemController(msg);
0896     auto filled= msg->uint8();
0897     auto penWidth= msg->uint16();
0898     auto x= msg->real();
0899     auto y= msg->real();
0900     auto w= msg->real();
0901     auto h= msg->real();
0902     hash.insert({Core::vmapkeys::KEY_FILLED, filled});
0903     hash.insert({Core::vmapkeys::KEY_PENWIDTH, penWidth});
0904     hash.insert({Core::vmapkeys::KEY_RECT, QRectF(x, y, w, h)});
0905     return hash;
0906 }
0907 
0908 void MessageHelper::addEllipseController(const vmap::EllipseController* ctrl, NetworkMessageWriter& msg)
0909 {
0910     addVisualItemController(ctrl, msg);
0911     msg.uint8(ctrl->filled());
0912     msg.uint16(ctrl->penWidth());
0913     msg.real(ctrl->rx());
0914     msg.real(ctrl->ry());
0915 }
0916 
0917 void MessageHelper::addLineController(const vmap::LineController* ctrl, NetworkMessageWriter& msg)
0918 {
0919     if(!ctrl)
0920         return;
0921     addVisualItemController(ctrl, msg);
0922     auto start= ctrl->startPoint();
0923     msg.real(start.x());
0924     msg.real(start.y());
0925 
0926     msg.uint16(ctrl->penWidth());
0927 
0928     auto end= ctrl->endPoint();
0929     msg.real(end.x());
0930     msg.real(end.y());
0931 }
0932 
0933 const std::map<QString, QVariant> MessageHelper::readLine(NetworkMessageReader* msg)
0934 {
0935     auto hash= readVisualItemController(msg);
0936     auto x1= msg->real();
0937     auto y1= msg->real();
0938 
0939     auto penWidth= msg->uint16();
0940 
0941     auto x2= msg->real();
0942     auto y2= msg->real();
0943     hash.insert({Core::vmapkeys::KEY_ENDPOINT, QPointF(x1, y1)});
0944     hash.insert({Core::vmapkeys::KEY_STARTPOINT, QPointF(x2, y2)});
0945     hash.insert({Core::vmapkeys::KEY_PENWIDTH, penWidth});
0946     return hash;
0947 }
0948 
0949 void MessageHelper::addImageController(const vmap::ImageItemController* ctrl, NetworkMessageWriter& msg)
0950 {
0951     if(!ctrl)
0952         return;
0953     addVisualItemController(ctrl, msg);
0954     msg.real(ctrl->ratio());
0955     msg.byteArray32(ctrl->data());
0956     auto rect= ctrl->rect();
0957     msg.real(rect.x());
0958     msg.real(rect.y());
0959     msg.real(rect.width());
0960     msg.real(rect.height());
0961 }
0962 
0963 const std::map<QString, QVariant> MessageHelper::readImage(NetworkMessageReader* msg)
0964 {
0965     auto hash= readVisualItemController(msg);
0966     auto ratio= msg->real();
0967     auto data= msg->byteArray32();
0968     auto x= msg->real();
0969     auto y= msg->real();
0970     auto w= msg->real();
0971     auto h= msg->real();
0972     hash.insert({Core::vmapkeys::KEY_RATIO, ratio});
0973     hash.insert({Core::vmapkeys::KEY_DATA, data});
0974     hash.insert({Core::vmapkeys::KEY_RECT, QRectF(x, y, w, h)});
0975     return hash;
0976 }
0977 
0978 void MessageHelper::addTextController(const vmap::TextController* ctrl, NetworkMessageWriter& msg)
0979 {
0980     if(!ctrl)
0981         return;
0982     addVisualItemController(ctrl, msg);
0983     msg.string32(ctrl->text());
0984     msg.uint16(ctrl->penWidth());
0985     msg.uint8(ctrl->border());
0986 
0987     auto p= ctrl->textPos();
0988     msg.real(p.x());
0989     msg.real(p.y());
0990 
0991     auto rect= ctrl->textRect();
0992     msg.real(rect.x());
0993     msg.real(rect.y());
0994     msg.real(rect.width());
0995     msg.real(rect.height());
0996 
0997     rect= ctrl->borderRect();
0998     msg.real(rect.x());
0999     msg.real(rect.y());
1000     msg.real(rect.width());
1001     msg.real(rect.height());
1002 }
1003 
1004 const std::map<QString, QVariant> MessageHelper::readText(NetworkMessageReader* msg)
1005 {
1006     auto hash= readVisualItemController(msg);
1007     auto text= msg->string32();
1008     auto penWidth= msg->uint16();
1009     auto border= static_cast<bool>(msg->uint8());
1010 
1011     auto x= msg->real();
1012     auto y= msg->real();
1013     QPointF textPos(x, y);
1014 
1015     x= msg->real();
1016     y= msg->real();
1017     auto w= msg->real();
1018     auto h= msg->real();
1019     QRectF textRect(x, y, w, h);
1020 
1021     x= msg->real();
1022     y= msg->real();
1023     w= msg->real();
1024     h= msg->real();
1025     QRectF borderRect(x, y, w, h);
1026 
1027     hash.insert({Core::vmapkeys::KEY_TEXT, text});
1028     hash.insert({Core::vmapkeys::KEY_PENWIDTH, penWidth});
1029     hash.insert({Core::vmapkeys::KEY_BORDER, border});
1030     hash.insert({Core::vmapkeys::KEY_BORDERRECT, borderRect});
1031     hash.insert({Core::vmapkeys::KEY_TEXTPOS, textPos});
1032     hash.insert({Core::vmapkeys::KEY_TEXTRECT, textRect});
1033 
1034     return hash;
1035 }
1036 
1037 void MessageHelper::addPathController(const vmap::PathController* ctrl, NetworkMessageWriter& msg)
1038 {
1039     if(!ctrl)
1040         return;
1041 
1042     addVisualItemController(ctrl, msg);
1043     msg.uint8(ctrl->filled());
1044     msg.uint8(ctrl->closed());
1045     msg.uint8(ctrl->penLine());
1046     msg.uint16(ctrl->penWidth());
1047     auto const& points= ctrl->points();
1048     msg.uint64(static_cast<quint64>(points.size()));
1049     for(auto p : points)
1050     {
1051         msg.real(p.x());
1052         msg.real(p.y());
1053     }
1054 }
1055 
1056 const std::map<QString, QVariant> MessageHelper::readPath(NetworkMessageReader* msg)
1057 {
1058     auto hash= readVisualItemController(msg);
1059     auto filled= static_cast<bool>(msg->uint8());
1060     auto closed= static_cast<bool>(msg->uint8());
1061     auto penLine= static_cast<bool>(msg->uint8());
1062     auto penWidth= msg->uint16();
1063     auto count= msg->uint64();
1064 
1065     std::vector<QPointF> points;
1066     points.reserve(static_cast<std::size_t>(count));
1067     for(unsigned int i= 0; i < count; ++i)
1068     {
1069         auto x= msg->real();
1070         auto y= msg->real();
1071         points.push_back(QPointF(x, y));
1072     }
1073     hash.insert({Core::vmapkeys::KEY_FILLED, filled});
1074     hash.insert({Core::vmapkeys::KEY_CLOSED, closed});
1075     hash.insert({Core::vmapkeys::KEY_PENLINE, penLine});
1076     hash.insert({Core::vmapkeys::KEY_PENWIDTH, penWidth});
1077     hash.insert({Core::vmapkeys::KEY_POINTS, QVariant::fromValue(points)});
1078 
1079     return hash;
1080 }
1081 
1082 void readCharacterVision(NetworkMessageReader* msg, std::map<QString, QVariant>& maps)
1083 {
1084     auto x= msg->real();
1085     auto y= msg->real();
1086 
1087     QPointF position(x, y);
1088 
1089     qreal angle= msg->real();
1090     CharacterVision::SHAPE visionShapeV= static_cast<CharacterVision::SHAPE>(msg->uint8());
1091     bool visible= static_cast<bool>(msg->uint8());
1092     qreal radiusV= msg->real();
1093 
1094     maps.insert({Core::vmapkeys::KEY_VIS_POS, position});
1095     maps.insert({Core::vmapkeys::KEY_VIS_ANGLE, angle});
1096     maps.insert({Core::vmapkeys::KEY_VIS_SHAPE, visionShapeV});
1097     maps.insert({Core::vmapkeys::KEY_VIS_VISIBLE, visible});
1098     maps.insert({Core::vmapkeys::KEY_VIS_RADIUS, radiusV});
1099 }
1100 
1101 const std::map<QString, QVariant> MessageHelper::readCharacter(NetworkMessageReader* msg)
1102 {
1103     auto hash= readVisualItemController(msg);
1104     auto side= msg->real();
1105     auto stateColor= QColor(msg->rgb());
1106     auto number= msg->uint32();
1107     auto playableCharacter= static_cast<bool>(msg->uint8());
1108 
1109     auto tx= msg->real();
1110     auto ty= msg->real();
1111     auto tw= msg->real();
1112     auto th= msg->real();
1113     QRectF textRect(tx, ty, tw, th);
1114 
1115     auto font= QFont(msg->string32());
1116     auto radius= msg->real();
1117 
1118     readCharacterVision(msg, hash);
1119 
1120     auto hasCharacter= static_cast<bool>(msg->uint8());
1121     hash.insert({Core::vmapkeys::KEY_SIDE, side});
1122     hash.insert({Core::vmapkeys::KEY_STATECOLOR, stateColor});
1123     hash.insert({Core::vmapkeys::KEY_NUMBER, number});
1124     hash.insert({Core::vmapkeys::KEY_PLAYABLECHARACTER, playableCharacter});
1125     hash.insert({Core::vmapkeys::KEY_FONT, font});
1126     hash.insert({Core::vmapkeys::KEY_RADIUS, radius});
1127     hash.insert({Core::vmapkeys::KEY_TEXTRECT, textRect});
1128     if(hasCharacter)
1129     {
1130         QString parentId;
1131         auto character= PlayerMessageHelper::readCharacter(*msg, parentId);
1132         hash.insert({Core::vmapkeys::KEY_CHARACTER, QVariant::fromValue(character)});
1133         if(!character)
1134             hash.insert({Core::vmapkeys::KEY_CHARAC_ID, QVariant::fromValue(character->uuid())});
1135         hash.insert({Core::vmapkeys::KEY_PARENTID, parentId});
1136     }
1137 
1138     return hash;
1139 }
1140 
1141 void MessageHelper::addCharacterController(const vmap::CharacterItemController* ctrl, NetworkMessageWriter& msg)
1142 {
1143     if(!ctrl)
1144         return;
1145     addVisualItemController(ctrl, msg);
1146     msg.real(ctrl->side());
1147     msg.rgb(ctrl->stateColor().rgb());
1148     msg.uint32(static_cast<quint32>(ctrl->number()));
1149     msg.uint8(ctrl->playableCharacter());
1150 
1151     auto rect= ctrl->textRect();
1152     msg.real(rect.x());
1153     msg.real(rect.y());
1154     msg.real(rect.width());
1155     msg.real(rect.height());
1156 
1157     msg.string32(ctrl->font().toString());
1158     msg.real(ctrl->radius());
1159 
1160     PlayerMessageHelper::writeVisionIntoMessage(msg, ctrl->vision());
1161 
1162     auto character= ctrl->character();
1163     msg.uint8(nullptr != character);
1164     if(nullptr != character)
1165     {
1166         PlayerMessageHelper::writeCharacterIntoMessage(msg, character);
1167     }
1168 }
1169 
1170 QHash<QString, QVariant> MessageHelper::readVectorialMapData(NetworkMessageReader* msg)
1171 {
1172     if(nullptr == msg)
1173         return {};
1174 
1175     QHash<QString, QVariant> hash;
1176     hash[Core::keys::KEY_UUID]= msg->string8();
1177     hash[Core::keys::KEY_NAME]= msg->string16();
1178     hash[Core::keys::KEY_LAYER]= msg->uint8();
1179     hash[Core::keys::KEY_PERMISSION]= msg->uint8();
1180     hash[Core::keys::KEY_BGCOLOR]= QColor(msg->rgb());
1181     hash[Core::keys::KEY_VISIBILITY]= msg->uint8();
1182     hash[Core::keys::KEY_ZINDEX]= msg->uint64();
1183     hash[Core::keys::KEY_CHARACTERVISION]= msg->uint8();
1184     hash[Core::keys::KEY_GRIDPATTERN]= msg->uint8();
1185     hash[Core::keys::KEY_GRIDVISIBILITY]= msg->uint8();
1186     hash[Core::keys::KEY_GRIDSIZE]= msg->uint32();
1187     hash[Core::keys::KEY_GRIDSCALE]= msg->real();
1188     hash[Core::keys::KEY_GRIDABOVE]= msg->uint8();
1189     hash[Core::keys::KEY_COLLISION]= msg->uint8();
1190     hash[Core::keys::KEY_UNIT]= msg->uint8();
1191     hash[Core::keys::KEY_GRIDCOLOR]= QColor(msg->rgb());
1192 
1193     hash[Core::keys::KEY_SIGHT]= readSightController(msg);
1194 
1195     auto itemCount= msg->uint64();
1196     QHash<QString, QVariant> items;
1197     for(quint64 i= 0; i < itemCount; ++i)
1198     {
1199         auto restore= msg->pos();
1200         auto type= static_cast<vmap::VisualItemController::ItemType>(msg->uint8());
1201         msg->resetToPos(restore);
1202         std::map<QString, QVariant> map;
1203         switch(type)
1204         {
1205         case vmap::VisualItemController::LINE:
1206             map= readLine(msg);
1207             break;
1208         case vmap::VisualItemController::PATH:
1209             map= readPath(msg);
1210             break;
1211         case vmap::VisualItemController::RECT:
1212             map= readRect(msg);
1213             break;
1214         case vmap::VisualItemController::TEXT:
1215             map= readText(msg);
1216             break;
1217         case vmap::VisualItemController::ELLIPSE:
1218             map= readEllipse(msg);
1219             break;
1220         case vmap::VisualItemController::CHARACTER:
1221             map= readCharacter(msg);
1222             break;
1223         case vmap::VisualItemController::IMAGE:
1224             map= readImage(msg);
1225             break;
1226         default:
1227             break;
1228         }
1229         QHash<QString, QVariant> qvals(map.begin(), map.end());
1230         items.insert(QString("Item_%1").arg(i), qvals);
1231     }
1232     hash[Core::keys::KEY_ITEMS]= items;
1233 
1234     return hash;
1235 }
1236 
1237 void MessageHelper::convertVisualItemCtrlAndAdd(vmap::VisualItemController* ctrl, NetworkMessageWriter& msg)
1238 {
1239     switch(ctrl->itemType())
1240     {
1241     case vmap::VisualItemController::LINE:
1242         addLineController(dynamic_cast<vmap::LineController*>(ctrl), msg);
1243         break;
1244     case vmap::VisualItemController::PATH:
1245         addPathController(dynamic_cast<vmap::PathController*>(ctrl), msg);
1246         break;
1247     case vmap::VisualItemController::RECT:
1248         addRectController(dynamic_cast<vmap::RectController*>(ctrl), msg);
1249         break;
1250     case vmap::VisualItemController::TEXT:
1251         addTextController(dynamic_cast<vmap::TextController*>(ctrl), msg);
1252         break;
1253     case vmap::VisualItemController::ELLIPSE:
1254         addEllipseController(dynamic_cast<vmap::EllipseController*>(ctrl), msg);
1255         break;
1256     case vmap::VisualItemController::CHARACTER:
1257         addCharacterController(dynamic_cast<vmap::CharacterItemController*>(ctrl), msg);
1258         break;
1259     case vmap::VisualItemController::IMAGE:
1260         addImageController(dynamic_cast<vmap::ImageItemController*>(ctrl), msg);
1261         break;
1262     default:
1263         break;
1264     }
1265 }
1266 
1267 void MessageHelper::sendOffVMap(VectorialMapController* ctrl)
1268 {
1269     if(nullptr == ctrl)
1270         return;
1271 
1272     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddMedia);
1273     msg.uint8(static_cast<quint8>(ctrl->contentType()));
1274     msg.string8(ctrl->uuid());
1275 
1276     msg.string16(ctrl->name());
1277     msg.uint8(static_cast<quint8>(ctrl->layer()));
1278     msg.uint8(static_cast<quint8>(ctrl->permission()));
1279     msg.rgb(ctrl->backgroundColor().rgb());
1280     msg.uint8(static_cast<quint8>(ctrl->visibility()));
1281     msg.uint64(ctrl->zIndex());
1282     msg.uint8(ctrl->characterVision());
1283     msg.uint8(static_cast<quint8>(ctrl->gridPattern()));
1284     msg.uint8(ctrl->gridVisibility());
1285     msg.uint32(static_cast<quint32>(ctrl->gridSize()));
1286     msg.real(ctrl->gridScale());
1287     msg.uint8(ctrl->gridAbove());
1288     msg.uint8(ctrl->collision());
1289     msg.uint8(static_cast<quint8>(ctrl->scaleUnit()));
1290     msg.rgb(ctrl->gridColor().rgb());
1291 
1292     // sight item
1293     auto sightCtrl= ctrl->sightController();
1294     addSightController(sightCtrl, msg);
1295 
1296     auto model= ctrl->model();
1297     auto data= model->items();
1298 
1299     auto count= std::accumulate(std::begin(data), std::end(data), 0,
1300                                 [](int i, vmap::VisualItemController* ctrl)
1301                                 {
1302                                     qDebug() << ctrl->color().name(QColor::HexArgb);
1303                                     if(ctrl->color().name(QColor::HexArgb) == "#ffff2003")
1304                                         qDebug() << "display values" << ctrl->removed() << ctrl->visible()
1305                                                  << ctrl->opacity() << ctrl->remote();
1306                                     return i + (ctrl->removed() ? 0 : 1);
1307                                 });
1308 
1309     qDebug() << "Before sending map: " << count << "vs" << data.size();
1310 
1311     msg.uint64(data.size());
1312 
1313     std::for_each(data.begin(), data.end(),
1314                   [&](vmap::VisualItemController* ctrl) { convertVisualItemCtrlAndAdd(ctrl, msg); });
1315 
1316     msg.sendToServer();
1317 }
1318 
1319 void MessageHelper::sendOffRect(const vmap::RectController* ctrl, const QString& mapId)
1320 {
1321     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1322     msg.string8(mapId);
1323     // msg.uint8(ctrl->itemType());
1324     addRectController(ctrl, msg);
1325     msg.sendToServer();
1326 }
1327 
1328 const std::map<QString, QVariant> MessageHelper::readEllipse(NetworkMessageReader* msg)
1329 {
1330     auto hash= readVisualItemController(msg);
1331     auto filled= msg->uint8();
1332     auto penWidth= msg->uint16();
1333     auto rx= msg->real();
1334     auto ry= msg->real();
1335     hash.insert({Core::vmapkeys::KEY_FILLED, filled});
1336     hash.insert({Core::vmapkeys::KEY_PENWIDTH, penWidth});
1337     hash.insert({Core::vmapkeys::KEY_RX, rx});
1338     hash.insert({Core::vmapkeys::KEY_RY, ry});
1339     return hash;
1340 }
1341 
1342 void MessageHelper::sendOffText(const vmap::TextController* ctrl, const QString& mapId)
1343 {
1344     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1345     msg.string8(mapId);
1346     // msg.uint8(ctrl->itemType());
1347     addTextController(ctrl, msg);
1348     msg.sendToServer();
1349 }
1350 
1351 void MessageHelper::sendOffLine(const vmap::LineController* ctrl, const QString& mapId)
1352 {
1353     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1354     msg.string8(mapId);
1355     // msg.uint8(ctrl->itemType());
1356     addLineController(ctrl, msg);
1357     msg.sendToServer();
1358 }
1359 
1360 void MessageHelper::sendOffEllispe(const vmap::EllipseController* ctrl, const QString& mapId)
1361 {
1362     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1363     msg.string8(mapId);
1364     // msg.uint8(ctrl->itemType());
1365     addEllipseController(ctrl, msg);
1366     msg.sendToServer();
1367 }
1368 void MessageHelper::sendOffPath(const vmap::PathController* ctrl, const QString& mapId)
1369 {
1370     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1371     msg.string8(mapId);
1372     addPathController(ctrl, msg);
1373     msg.sendToServer();
1374 }
1375 void MessageHelper::sendOffImage(const vmap::ImageItemController* ctrl, const QString& mapId)
1376 {
1377     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1378     msg.string8(mapId);
1379     addImageController(ctrl, msg);
1380     msg.sendToServer();
1381 }
1382 void MessageHelper::sendOffCharacter(const vmap::CharacterItemController* ctrl, const QString& mapId)
1383 {
1384     NetworkMessageWriter msg(NetMsg::VMapCategory, NetMsg::AddItem);
1385     msg.string8(mapId);
1386     addCharacterController(ctrl, msg);
1387     msg.sendToServer();
1388 }
1389 
1390 void MessageHelper::readAddSubImage(mindmap::ImageModel* model, NetworkMessageReader* msg)
1391 {
1392     if(!msg || !model)
1393         return;
1394     auto pix= IOHelper::dataToPixmap(msg->byteArray32());
1395     auto id= msg->string8();
1396     auto url= QUrl(msg->string16());
1397     if(pix.isNull())
1398         return;
1399     model->insertPixmap(id, pix, url, true);
1400 }
1401 
1402 void MessageHelper::readRemoveSubImage(mindmap::ImageModel* model, NetworkMessageReader* msg)
1403 {
1404     if(!msg || !model)
1405         return;
1406     model->removePixmap(msg->string8());
1407 }
1408 
1409 void MessageHelper::sendOffImageInfo(const mindmap::ImageInfo& info, MediaControllerBase* ctrl)
1410 {
1411     if(!ctrl || info.m_pixmap.isNull())
1412         return;
1413 
1414     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddSubImage);
1415     msg.int8(static_cast<int>(ctrl->contentType()));
1416     msg.string8(ctrl->uuid());
1417     msg.byteArray32(IOHelper::pixmapToData(info.m_pixmap));
1418     msg.string8(info.m_id);
1419     msg.string16(info.m_url.toString());
1420     msg.sendToServer();
1421 }
1422 
1423 void MessageHelper::sendOffRemoveImageInfo(const QString& id, MediaControllerBase* ctrl)
1424 {
1425     if(!ctrl)
1426         return;
1427 
1428     NetworkMessageWriter msg(NetMsg::MediaCategory, NetMsg::AddSubImage);
1429     msg.int8(static_cast<int>(ctrl->contentType()));
1430     msg.string8(ctrl->uuid());
1431     msg.string8(id);
1432     msg.sendToServer();
1433 }
1434 
1435 void buildAddLinkMessage(NetworkMessageWriter& msg, QList<mindmap::LinkController*> links)
1436 {
1437     msg.uint64(links.size());
1438     for(auto link : links)
1439     {
1440         Q_ASSERT(link);
1441         msg.string8(link->id());
1442         msg.string32(link->text());
1443         msg.string8(link->start()->id());
1444         auto end= link->end();
1445         msg.string8(end ? end->id() : QString());
1446         msg.uint8(static_cast<quint8>(link->direction()));
1447     }
1448 }
1449 
1450 void buildAddNodeMessage(NetworkMessageWriter& msg, QList<mindmap::MindNode*> nodes)
1451 {
1452     msg.uint64(nodes.size());
1453     for(auto node : nodes)
1454     {
1455 
1456         msg.string8(node->id());
1457         auto f= node->position();
1458         msg.real(f.x());
1459         msg.real(f.y());
1460         msg.string32(node->text());
1461         msg.string8(node->imageUri());
1462         msg.string8(node->parentId());
1463         msg.uint64(node->styleIndex());
1464 
1465         auto subs= node->subLinks();
1466         msg.uint64(static_cast<quint64>(subs.size()));
1467         for(const auto& link : subs)
1468         {
1469             msg.string8(link->id());
1470         }
1471     }
1472 }
1473 void readMindMapLink(MindMapController* ctrl, NetworkMessageReader* msg)
1474 {
1475     if(!ctrl || !msg)
1476         return;
1477 
1478     QList<mindmap::LinkController*> links;
1479 
1480     auto count= msg->uint64();
1481 
1482     for(quint64 i= 0; i < count; ++i)
1483     {
1484         auto id= msg->string8();
1485         auto text= msg->string32();
1486         auto idStart= msg->string8();
1487         auto idEnd= msg->string8();
1488 
1489         auto dir= static_cast<mindmap::LinkController::Direction>(msg->uint8());
1490 
1491         auto start= ctrl->nodeFromId(idStart);
1492         auto end= ctrl->nodeFromId(idEnd);
1493 
1494         if(!start || !end)
1495             continue;
1496 
1497         auto link= new mindmap::LinkController();
1498         link->setId(id);
1499         link->setText(text);
1500         link->setDirection(dir);
1501         link->setStart(start);
1502         link->setEnd(end);
1503         links.append(link);
1504     }
1505 
1506     ctrl->addLink(links, true);
1507 }
1508 
1509 void readAddMindMapNode(MindMapController* ctrl, NetworkMessageReader* msg)
1510 {
1511     if(!ctrl || !msg)
1512         return;
1513 
1514     QList<mindmap::MindNode*> nodes;
1515     QList<QPair<QString, QString>> parentIdList;
1516 
1517     auto count= msg->uint64();
1518 
1519     for(quint64 i= 0; i < count; ++i)
1520     {
1521 
1522         auto id= msg->string8();
1523         auto x= msg->real();
1524         auto y= msg->real();
1525         auto text= msg->string32();
1526         auto uri= msg->string8();
1527         auto parentId= msg->string8();
1528         auto indx= msg->uint64();
1529 
1530         auto count= msg->uint64();
1531         QStringList list;
1532         for(quint64 i= 0; i < count; ++i)
1533         {
1534             list << msg->string8();
1535         }
1536 
1537         mindmap::MindNode* node= new mindmap::MindNode(ctrl);
1538         node->setPosition(QPointF(x, y));
1539         node->setText(text);
1540         node->setId(id);
1541         node->setImageUri(uri);
1542         if(!parentId.isEmpty())
1543         {
1544             auto parent= ctrl->nodeFromId(parentId);
1545             node->setParentNode(parent);
1546         }
1547         node->setStyleIndex(indx);
1548         ctrl->addNode({node}, true);
1549 
1550         if(!parentId.isNull())
1551             parentIdList.append({parentId, id});
1552         // ctrl->createLink(parentId, id);
1553 
1554         for(const auto& tmp : qAsConst(list))
1555             parentIdList.append({id, tmp});
1556         //  ctrl->createLink(id, tmp);
1557     }
1558     ctrl->addNode(nodes, true);
1559 }
1560 void MessageHelper::readMindMapAddItem(MindMapController* ctrl, NetworkMessageReader* msg)
1561 {
1562     readAddMindMapNode(ctrl, msg);
1563     readMindMapLink(ctrl, msg);
1564 }
1565 
1566 void MessageHelper::buildAddItemMessage(NetworkMessageWriter& msg, const QList<mindmap::MindNode*>& nodes,
1567                                         const QList<mindmap::LinkController*>& links)
1568 {
1569     buildAddNodeMessage(msg, nodes);
1570     buildAddLinkMessage(msg, links);
1571 }
1572 void MessageHelper::buildRemoveItemMessage(NetworkMessageWriter& msg, const QStringList& nodes,
1573                                            const QStringList& links)
1574 {
1575 
1576     auto func= [&msg](const QString& id) { msg.string8(id); };
1577     msg.uint64(nodes.size());
1578     std::for_each(std::begin(nodes), std::end(nodes), func);
1579 
1580     msg.uint64(links.size());
1581     std::for_each(std::begin(links), std::end(links), func);
1582 }
1583 
1584 void MessageHelper::readMindMapRemoveMessage(MindMapController* ctrl, NetworkMessageReader* msg)
1585 {
1586     auto nodes= readIdList(*msg);
1587     auto links= readIdList(*msg);
1588 
1589     ctrl->removeNode(nodes);
1590     ctrl->removeLink(links);
1591 }
1592 
1593 QStringList MessageHelper::readIdList(NetworkMessageReader& data)
1594 {
1595     QStringList res;
1596     auto count= data.uint64();
1597 
1598     for(quint64 i= 0; i < count; ++i)
1599     {
1600         if(data.isValid())
1601             res << data.string8();
1602     }
1603 
1604     return res;
1605 }
1606 
1607 void MessageHelper::fetchCharacterStatesFromNetwork(NetworkMessageReader* msg, CharacterStateModel* model)
1608 {
1609     model->clear();
1610     auto size= msg->uint32();
1611     for(quint32 i= 0; i < size; ++i)
1612     {
1613         auto label= msg->string32();
1614         auto color= msg->rgb();
1615         auto pixmap= msg->pixmap();
1616         CharacterState state;
1617         state.setLabel(label);
1618         state.setColor(color);
1619         state.setPixmap(pixmap);
1620         model->appendState(std::move(state));
1621     }
1622 }
1623 
1624 void MessageHelper::fetchDiceAliasFromNetwork(NetworkMessageReader* msg, QList<DiceAlias*>* list)
1625 {
1626     qDeleteAll(*list);
1627     list->clear();
1628     auto size= msg->uint32();
1629     for(quint32 i= 0; i < size; ++i)
1630     {
1631         msg->uint64();
1632 
1633         auto pattern= msg->string32();
1634         auto command= msg->string32();
1635         auto replace= msg->int8();
1636         auto enable= msg->int8();
1637         auto comment= msg->string32();
1638 
1639         list->append(new DiceAlias(pattern, command, comment, replace, enable));
1640     }
1641 }
1642 
1643 /*void MessageHelper::AddCharacterStateFromNetwork(NetworkMessageReader* msg, QList<DiceAlias*>* list)
1644 {
1645     CharacterState state;
1646 
1647     quint64 id= msg->uint64();
1648     state.setLabel(msg->string32());
1649     state.setColor(msg->rgb());
1650     state.setPixmap(msg->pixmap());
1651 
1652     model->appendState(std::move(state));
1653 }
1654 void MessageHelper::moveStateFromNetwork(NetworkMessageReader* msg, CharacterStateModel* model)
1655 {
1656     int from= msg->int64();
1657     int to= msg->int64();
1658 
1659     model->moveState(from, to);
1660 }
1661 void MessageHelper::removeState(NetworkMessageReader* msg, CharacterStateModel* model)
1662 {
1663     int pos= static_cast<int>(msg->int64());
1664     model->removeStateAt(pos);
1665 }
1666 */
1667 
1668 void MessageHelper::sendOffPlaySong(const QString& songName, qint64 time, int player)
1669 {
1670     qDebug() << "sendOffPlaySong: " << songName << player;
1671     NetworkMessageWriter msg(NetMsg::MusicCategory, NetMsg::NewSong);
1672     msg.uint8(static_cast<quint8>(player));
1673     msg.string32(songName);
1674     msg.int64(time);
1675     msg.sendToServer();
1676 }
1677 void MessageHelper::sendOffMusicPlayerOrder(NetMsg::Action netAction, int player)
1678 {
1679     qDebug() << "sendOffMusicPlayerOrder: " << netAction << player;
1680     NetworkMessageWriter message(NetMsg::MusicCategory, netAction);
1681     message.uint8(static_cast<quint8>(player));
1682     message.sendToServer();
1683 }
1684 void MessageHelper::sendOffTime(qint64 time, int player)
1685 {
1686     qDebug() << "sendOffTime: " << time << player;
1687     NetworkMessageWriter message(NetMsg::MusicCategory, NetMsg::ChangePositionSong);
1688     message.uint8(static_cast<quint8>(player));
1689     message.int64(time);
1690     message.sendToServer();
1691 }