Implemented copy, cut and paste frame
[dashstudio.git] / src / dashserver / project / project.cpp
blobb09edec0c5cd3c6d324afc4a9e8cbe822178fd73
1 /***************************************************************************
2 * Copyright (C) 2007 by David Cuadrado *
3 * krawek@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
22 #include "project.h"
24 #include <QSet>
25 #include <QXmlStreamReader>
27 #include <yamf/model/command/processor.h>
29 #include "dashserver/connection.h"
30 #include "dashserver/logger.h"
31 #include "dashserver/xdbms/manager.h"
33 #include "dash/projectsaver.h"
34 #include "dash/network/package/transfer.h"
36 #include "member.h"
37 #include "commandprocessor.h"
39 #include <dcore/debug.h>
41 namespace DashServer {
42 namespace Project {
44 struct Project::Private
46 Private(Project *q) : q(q), initialized(false) {}
48 Project *q;
49 bool initialized;
50 CommandProcessor *processor;
52 QSet<DashServer::Connection *> connections;
54 QHash<QString, Member *> members;
57 void loadMembers();
60 void Project::Private::loadMembers()
62 members.clear();
64 QList<XDBMS::Object *> objects = q->objects();
66 foreach(XDBMS::Object *obj, objects)
68 if( obj->klass() == "member" )
70 Member *member = static_cast<Member *>(obj);
71 members[member->id()] = member;
75 initialized = true;
78 Project::Project(QObject *parent) : Dash::Project(parent), XDBMS::Object(), d(new Private(this))
80 d->processor = new CommandProcessor(this);
82 setClass("project");
86 Project::~Project()
88 delete d->processor;
89 delete d;
92 void Project::execute(const QString &xml, DashServer::Connection *source)
94 if( d->connections.contains(source) )
96 QString cmdname;
99 QXmlStreamReader reader(xml);
100 while(!reader.atEnd())
102 if( reader.readNext() == QXmlStreamReader::StartElement )
104 if( reader.name() == "command" )
106 cmdname = reader.attributes().value("name").toString();
107 break;
113 Member *member = d->members.value(source->user()->login());
114 int part = Project::partFromCommand(cmdname);
116 if( ! member->canWriteOn(part) )
118 DashServer::Logger::self()->info(QString("Permission denied: User %1 trying to write on %2").arg(member->id(), Project::partName(part)));
120 source->sendToClient( "<command />\n", true );
121 source->sendError(tr("Permission denied"), Dash::Network::Package::Error::Err);
122 return;
125 if( d->processor->execute(xml) )
127 QString tosend = source->signXml(xml);
129 foreach(DashServer::Connection *cnx, d->connections)
131 if( d->members[cnx->user()->login()]->canReadOn(part) )
133 cnx->sendToClient( tosend, false );
137 else
139 source->sendToClient( "<command />", true ); // FIXME: create a package
142 else
144 qWarning("INVALID SOURCE");
148 void Project::addClient(DashServer::Connection *cnx)
150 d->connections << cnx;
153 void Project::removeClient(DashServer::Connection *client)
155 d->connections.remove(client);
157 if( d->connections.isEmpty() )
159 save();
163 void Project::sendToClient(DashServer::Connection *client)
165 // FIXME: Poner en un thread
167 QFile f(this->fileName());
168 Dash::Network::Package::Transfer transfer(f.size());
169 client->sendToClient(transfer.toString(), true);
171 if( f.open(QIODevice::ReadOnly) )
173 while(!f.atEnd())
175 client->sendBinaryData(f.read(1024));
181 void Project::sendToAll()
183 save();
186 QFile f(this->fileName());
188 foreach(DashServer::Connection *client, d->connections)
190 Dash::Network::Package::Transfer transfer(f.size());
191 client->sendToClient(transfer.toString(), true);
194 if( f.open(QIODevice::ReadOnly) )
196 while(!f.atEnd())
198 foreach(DashServer::Connection *client, d->connections)
200 client->sendBinaryData(f.read(1024));
207 QHash<QString, Member *> Project::members() const
209 return d->members;
212 QSet<DashServer::Connection *> Project::connections() const
214 return d->connections;
217 int Project::clientCount() const
219 return d->connections.size();
222 void Project::aboutToSave()
224 if( projectName().isEmpty() ) return;
226 setId(projectName());
228 add("description", description());
229 add("author", author());
231 if(!d->initialized) d->loadMembers();
234 void Project::afterLoad()
236 setProjectName(id());
237 setDescription(value("description"));
238 setAuthor(value("author"));
240 if(!d->initialized) d->loadMembers();
243 bool Project::save()
245 if(!d->initialized) d->loadMembers();
247 QString pname = projectName();
249 if( pname.isEmpty() ) return false;
251 return Dash::ProjectSaver::save(this, fileName());
254 bool Project::load()
256 if(!d->initialized) d->loadMembers();
258 QString pname = projectName();
260 if( pname.isEmpty() )
262 qWarning("Warning: Project name is empty");
263 return false;
266 clear();
268 return Dash::ProjectSaver::load(this, fileName());
271 QString Project::fileName() const
273 QString pname = projectName();
275 if( pname.isEmpty() )
276 return QString();
278 return XDBMS::Manager::self()->databaseDir().absoluteFilePath(pname+".dsh");
281 void Project::addMember(Member *member)
283 if( d->members.contains(member->id()) )
285 d->members.remove(member->id());
286 remove(member);
289 d->members[member->id()] = member;
290 add(member);
293 QString Project::partName(int part)
295 switch(part)
297 case All:
299 return "all";
301 break;
302 case Scene:
304 return "scene";
306 break;
307 case Layer:
309 return "layer";
311 break;
312 case Frame:
314 return "frame";
316 break;
317 case Object:
319 return "object";
321 break;
324 return QString();
328 int Project::partFromCommand(const QString &pkgname)
330 Project::Part part = Project::None;
332 // LIBRARY
333 if( pkgname == "addlibraryfolder" )
335 part = Project::Library;
337 else if( pkgname == "addlibraryobject" )
339 part = Project::Library;
341 else if( pkgname == "modifysymbol" )
343 part = Project::Library;
345 else if( pkgname == "renamelibraryobject" )
347 part = Project::Library;
351 // OBJECT AND ITEM
352 if( pkgname == "additemfilter" )
354 part = Project::Object;
356 else if( pkgname == "addobject" )
358 part = Project::Object;
360 else if( pkgname == "addtweening" )
362 part = Project::Object;
364 else if( pkgname == "bringforwardsitem" )
366 part = Project::Object;
368 else if( pkgname == "bringtofrontitem" )
370 part = Project::Object;
372 else if( pkgname == "changelayervisibility" )
374 part = Project::Object;
376 else if( pkgname == "changetextfont" )
378 part = Project::Object;
380 else if( pkgname == "changetext" )
382 part = Project::Object;
384 else if( pkgname == "changetextwidth" )
386 part = Project::Object;
388 else if( pkgname == "convertitem" )
390 part = Project::Object;
392 else if( pkgname == "editnodesitem" )
394 part = Project::Object;
396 else if( pkgname == "changeitembrush" )
398 part = Project::Object;
400 else if( pkgname == "changeitempen" )
402 part = Project::Object;
404 else if( pkgname == "groupitem" )
406 part = Project::Object;
408 else if( pkgname == "modifyfilter" )
410 part = Project::Object;
412 else if( pkgname == "modifyitem" )
414 part = Project::Object;
416 else if( pkgname == "removelibraryobject" )
418 part = Project::Object;
420 else if( pkgname == "removeobject" )
422 part = Project::Object;
424 else if( pkgname == "sendbackwardsitem" )
426 part = Project::Object;
428 else if( pkgname == "sendtobackitem" )
430 part = Project::Object;
432 else if( pkgname == "ungroupitem" )
434 part = Project::Object;
438 // FRAME
439 if( pkgname == "changeframevisibility" )
441 part = Project::Frame;
443 else if( pkgname == "expandframe" )
445 part = Project::Frame;
447 else if( pkgname == "insertframe" )
449 part = Project::Frame;
451 else if( pkgname == "lockframe" )
453 part = Project::Frame;
455 else if( pkgname == "moveframe" )
457 part = Project::Frame;
459 else if( pkgname == "removeframe" )
461 part = Project::Frame;
463 else if( pkgname == "renameframe" )
465 part = Project::Frame;
468 // LAYER
469 if( pkgname == "insertlayer" )
471 part = Project::Layer;
473 else if( pkgname == "locklayer" )
475 part = Project::Layer;
477 else if( pkgname == "movelayer" )
479 part = Project::Layer;
481 else if( pkgname == "removelayer" )
483 part = Project::Layer;
485 else if( pkgname == "renamelayer" )
487 part = Project::Layer;
491 // SCENE
492 if( pkgname == "insertscene" )
494 part = Project::Scene;
496 else if( pkgname == "movescene" )
498 part = Project::Scene;
500 else if( pkgname == "removescene" )
502 part = Project::Scene;
504 else if( pkgname == "renamescene" )
506 part = Project::Scene;
509 return part;