OSDN Git Service

[denncoCreator] Implemented cell code manager dialog. The implementation is incomplet...
[dennco/denncoCreator.git] / Source / dccontainer.cpp
1 //  Copyright (c) 2012 Dennco Project
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 //
17 //  Created by tkawata on Sep-30, 2012.
18 //
19 #include "dccontainer.h"
20
21 #include "dccell.h"
22 #include "dccellcode.h"
23 #include "dcaxon.h"
24 #include "dcaxonterminal.h"
25 #include "dcreceptor.h"
26 #include "dcscene.h"
27 #include "dccontent.h"
28 #include "dccreator.h"
29 #include "dcvpagecomponent.h"
30 #include "utils/dccomponentutil.h"
31 #include "dctreeviewwidget.h"
32
33 #include "DNFileList.h"
34 #include "DNDirectory.h"
35 #include "utils/dcutil.h"
36
37 #include <QMutexLocker>
38 #include <QDir>
39 #include <QDirIterator>
40
41
42 //static
43 TKContainer* TKContainer::createContainer()
44 {
45     TKContainer *container = new DCContainer();
46     container->init();
47     return container;
48 }
49
50 DCContainer::DCContainer() : d_content(NULL), d_factoryCachedLocation("")
51 {
52     d_scene = new DCScene(this);
53
54     d_workDirRoot = QDir::homePath() + "/.denncoCreator/work";
55     d_workDirCellRoot = d_workDirRoot + "/cells";
56     d_workDirCellCodeRoot = d_workDirRoot + "/cellcodes";
57
58 }
59
60 DCContainer::~DCContainer()
61 {
62     if (d_scene)
63     {
64         delete d_scene;
65         d_scene = NULL;
66     }
67 }
68
69 bool DCContainer::getIsModified() const
70 {
71     if (d_scene)
72     {
73         return d_scene->getIsModified();
74     }
75     else
76     {
77         return false;
78     }
79 }
80
81 bool DCContainer::isScriptableCell(DCCell *cell)
82 {
83     bool    noScript = false;
84
85     std::string type = cell->getType().toStdString();
86
87     if (type == CELLTYPE_JSBASIC || type.length() == 0)
88     {
89         noScript = false;
90     }
91     else if (type == CELLTYPE_IN)
92     {
93         noScript = true;
94     }
95     else if (type == CELLTYPE_OUT)
96     {
97         noScript = true;
98     }
99     else if (type == CELLTYPE_BASICSTORAGE)
100     {
101         noScript = false;
102     }
103     else
104     {
105         Q_ASSERT(0);
106     }
107     return !noScript;
108 }
109
110 void DCContainer::setContent(DCContent *content)
111 {
112     d_content = content;
113 }
114
115 void DCContainer::unselectCellObjectAll()
116 {
117     for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it ) {
118         DCCell *cell = dynamic_cast<DCCell*>(it->second);
119         if (cell)
120             cell->getVComponent()->setSelected(false,true);
121     }
122 }
123
124 QList<DCVComponent*> DCContainer::getSelectedCellObjects() const
125 {
126     QList<DCVComponent*> list;
127
128     for ( TKCellMap::const_iterator it = mCells.begin(); it != mCells.end(); ++it ) {
129         DCCell *cell = dynamic_cast<DCCell*>(it->second);
130         if (cell)
131         {
132             DCVComponent *object = NULL;
133
134             object = cell->getVComponent();
135             if (object && object->getIsSelected())
136             {
137                 list.push_back(object);
138             }
139
140             //axon
141             DCAxon *axon = cell->getAxon();
142             object = axon->getVComponent();
143             if (object && object->getIsSelected())
144             {
145                 list.push_back(object);
146             }
147
148             //terminals
149             int n = axon->getNumberOfTerminals();
150             for (int i = 0; i < n; i++)
151             {
152                 object = axon->getTerminalAt(i)->getVComponent();
153                 if (object && object->getIsSelected())
154                 {
155                     list.push_back(object);
156                 }
157             }
158
159             //receptors
160             const TKReceptorMap *receptors = cell->getReceptors();
161             TKReceptorMap::const_iterator it = receptors->begin();
162             while( it != receptors->end())
163             {
164                 object = ((DCReceptor*)(*it).second)->getVComponent();
165                 if (object && object->getIsSelected())
166                 {
167                     list.push_back(object);
168                 }
169                 ++it;
170             }
171         }
172     }
173
174     return list;
175 }
176
177 TKCell* DCContainer::addCell(std::string theLocation, std::string theName, std::string type, std::string customScript)
178 {
179     QMutexLocker(d_scene->getSceneLock());
180
181     DCCell *cell = dynamic_cast<DCCell*>(TKContainer::addCell(theLocation, theName, type, customScript));
182
183     saveCustomScriptToWorkFile(cell, customScript);
184
185     return cell;
186 }
187
188 TKCell*  DCContainer::addCell(std::string theLocation, std::string theName, TKCellCode *cellCode, std::string customScript)
189 {
190     QMutexLocker(d_scene->getSceneLock());
191
192     DCCell *cell = dynamic_cast<DCCell*>(TKContainer::addCell(theLocation, theName, cellCode, customScript));
193
194     saveCustomScriptToWorkFile(cell, customScript);
195
196     return cell;
197 }
198
199 TKCellCode* DCContainer::addCellCode(std::string theName, std::string theAPIType, std::string code)
200 {
201     QMutexLocker(d_scene->getSceneLock());
202
203     DCCellCode *cellCode = dynamic_cast<DCCellCode*>(TKContainer::addCellCode(theName, theAPIType, code));
204
205     saveClassScriptToWorkFile(cellCode, code);
206
207     return cellCode;
208 }
209
210 TKCell* DCContainer::cellFactory(std::string location, std::string name, std::string type, bool canInterface)
211 {
212     if (location != d_factoryCachedLocation || d_factoryCachedPageObject.ref() == NULL)
213     {
214         d_factoryCachedPageObject.assign(d_scene->getPage(location));
215         if (d_factoryCachedPageObject.ref() == NULL)
216         {
217             d_factoryCachedPageObject.assign(d_scene->addPage(location));
218         }
219     }
220     d_factoryCachedLocation = location;
221
222     TKCell *cell = DCComponentUtil::createCell(this, dynamic_cast<DCVCPage*>(d_factoryCachedPageObject.ref()), location, name, type, canInterface);
223     cell->init();
224
225     return cell;
226 }
227
228 TKAxon* DCContainer::axonFactory(TKCell *theOwner)
229 {
230     return DCComponentUtil::createAxon((DCCell*)theOwner);
231 }
232
233 TKReceptor* DCContainer::receptorFactory(TKCell *theOwner)
234 {
235     return DCComponentUtil::createReceptor((DCCell*)theOwner);
236 }
237
238 TKAxonTerminal* DCContainer::axonTerminalFactory(TKAxon *theOwner)
239 {
240     return DCComponentUtil::createAxonTerminal((DCAxon*)theOwner);
241 }
242
243 TKCellCode* DCContainer::cellCodeFactory(std::string name, std::string cellapi, std::string code)
244 {
245     DCVCPage *page = NULL;
246     if (name != TKContainer::CELLCODENAME_EMPTY)
247     {
248         std::string location = name;
249         if (location.find("#") != std::string::npos)
250         {
251             location = location.substr(0, location.find("#"));
252         }
253         if (location != d_factoryCachedLocation || d_factoryCachedPageObject.ref() == NULL)
254         {
255             d_factoryCachedPageObject.assign(d_scene->getPage(location));
256             if (d_factoryCachedPageObject.ref() == NULL)
257             {
258                 d_factoryCachedPageObject.assign(d_scene->addPage(location));
259             }
260         }
261         d_factoryCachedLocation = location;
262         page = dynamic_cast<DCVCPage*>(d_factoryCachedPageObject.ref());
263     }
264     return DCComponentUtil::createCellCode(this, page, name, cellapi);
265 }
266
267 void DCContainer::beganParsePage(const char *docRoot, const char *path)
268 {
269     QDir workCellDir(d_workDirCellRoot + "/" + QString::fromLocal8Bit(path));
270     QDir workCellCodeDir(d_workDirCellCodeRoot + "/" + QString::fromLocal8Bit(path));
271     if (!workCellDir.exists())
272     {
273         workCellDir.mkpath(workCellDir.absolutePath());
274     }
275     if (!workCellCodeDir.exists())
276     {
277         workCellCodeDir.mkpath(workCellCodeDir.absolutePath());
278     }
279
280     std::string location = path;
281     d_factoryCachedPageObject.assign(d_scene->getPage(location));
282     if (d_factoryCachedPageObject.ref() == NULL)
283     {
284         d_factoryCachedPageObject.assign(d_scene->addPage(location));
285     }
286     d_factoryCachedLocation = location;
287 }
288
289 void DCContainer::endedParsePage(const char *docRoot, const char *path)
290 {
291
292 }
293
294
295 void DCContainer::beganBuildContainer()
296 {
297     DCUtil::removeDirRecursive(d_workDirRoot);
298 }
299
300 void DCContainer::endedBuildContainer()
301 {
302
303
304 }
305
306 bool DCContainer::removeCellCode(DCCellCode *cellcode)
307 {
308     for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it )
309     {
310         DCCell *cell = dynamic_cast<DCCell*>(it->second);
311         if (cell->getCellCode() == cellcode)
312         {
313             cell->setCellCode(mEmptyCellClass, cell->getCustomScript().toLocal8Bit().data());
314         }
315     }
316
317     bool found = false;
318     for ( TKCellCodeMap::iterator it = mCellCodes.begin(); it != mCellCodes.end(); ++it )
319     {
320         if (it->second == cellcode)
321         {
322             mCellCodes.erase(it);
323             found = true;
324             break;
325         }
326     }
327
328     if (cellcode->getPageBelonging())
329     {
330         cellcode->getPageBelonging()->unregisterCellCodeClass(cellcode->getVComponent());
331     }
332     delete cellcode;
333
334     return found;
335 }
336
337 bool DCContainer::removeCell(DCCell *cell)
338 {
339     for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it )
340     {
341         if (it->second == cell)
342         {
343             mCells.erase(it++);
344             if (cell->getPageBelonging())
345             {
346                 cell->getPageBelonging()->unregisterCell(cell->getVComponent());
347             }
348             delete cell;
349             return true;
350         }
351     }
352     return false;
353 }
354
355 bool DCContainer::saveCustomScriptToWorkFile(DCCell *cell, std::string customScript)
356 {
357     QDir workdir(d_workDirCellRoot + "/" + QString::fromStdString(cell->getLocation()));
358     if (!workdir.exists())
359     {
360         workdir.mkpath(workdir.absolutePath());
361     }
362     QFile workfile(workdir.absoluteFilePath(QString::fromStdString(cell->getName()) + ".js"));
363     workfile.open(QIODevice::WriteOnly);
364     QTextStream out(&workfile);
365     out << QString::fromStdString(customScript);
366     workfile.close();
367     return true;
368 }
369
370 bool DCContainer::saveClassScriptToWorkFile(DCCellCode *cellCode, std::string code)
371 {
372     QString qNamePath = QString::fromStdString(cellCode->getFQNName());
373     QString path = DCUtil::getContainerBasedPathFromFQNPath(qNamePath);
374     QString name = DCUtil::getNameFromFQNPath(qNamePath);
375
376     QDir workdir(d_workDirCellCodeRoot + "/" + path);
377     if (!workdir.exists())
378     {
379         workdir.mkpath(workdir.absolutePath());
380     }
381     QFile workfile(workdir.absoluteFilePath(name + ".js"));
382     workfile.open(QIODevice::WriteOnly);
383     QTextStream out(&workfile);
384     out << QString::fromStdString(code);
385     workfile.close();
386     return true;
387 }
388
389 QString DCContainer::readCustomScriptFromWorkFile(const DCCell *cell)
390 {
391     QFile file(d_workDirCellRoot + "/" + QString::fromStdString(cell->getLocation()) + "/" + QString::fromStdString(cell->getName()) + ".js");
392
393     if (!file.exists())
394     {
395         return "";
396     }
397
398     file.open(QIODevice::ReadOnly);
399     QTextStream in(&file);
400     QString out = in.readAll();
401     file.close();
402
403     return out;
404 }
405
406 QString DCContainer::readCellCodeScriptFromFile(const DCCellCode *cellCode)
407 {
408     QString qNamePath = QString::fromStdString(cellCode->getFQNName());
409     QString path = DCUtil::getContainerBasedPathFromFQNPath(qNamePath);
410     QString name = DCUtil::getNameFromFQNPath(qNamePath);
411
412     QFile file(d_workDirCellCodeRoot + "/" + path + "/" + name + ".js");
413     if (!file.exists())
414     {
415         return "";
416     }
417
418     file.open(QIODevice::ReadOnly);
419     QTextStream in(&file);
420     QString out = in.readAll();
421     file.close();
422
423     return out;
424 }
425
426 QString DCContainer::sysFilePathToContainerBasedPath(const QString &sysFilePath)
427 {
428     QString containerPath = QString::fromStdString(getContainerRootPath());
429     return "/" + QDir(containerPath).relativeFilePath(sysFilePath);
430 }
431
432 QString DCContainer::containerBasedPathToSysFilePath(const QString &containerBasedPath)
433 {
434     QString containerPath = QString::fromStdString(getContainerRootPath());
435     return containerPath + containerBasedPath;
436 }
437
438 bool DCContainer::renameCell(DCCell *cell, const QString &newName)
439 {
440     QString fqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
441     mCells.erase(fqnName.toStdString());
442
443     cell->changeName(newName);
444
445     QString newFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
446     std::pair<TKCellMap::iterator, bool> r = mCells.insert(TKCellMap::value_type(newFqnName.toStdString(), cell));
447
448     return r.second;
449 }
450
451 bool DCContainer::moveCell(DCCell *cell, const QString& pageNewContainerBasedPathName)
452 {
453     QString fqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
454     QString customScript = readCustomScriptFromWorkFile(cell);
455     mCells.erase(fqnName.toStdString());
456
457     cell->changePath(pageNewContainerBasedPathName);
458     saveCustomScriptToWorkFile(cell, customScript.toStdString());
459
460     QString newFqnName = DCUtil::getFQNPath(pageNewContainerBasedPathName.toStdString(), cell->getName());
461     std::pair<TKCellMap::iterator, bool> r = mCells.insert(TKCellMap::value_type(newFqnName.toStdString(), cell));
462     return r.second;
463 }
464
465 bool DCContainer::renameCellCodeClass(DCCellCode *cellcode, const QString &newName)
466 {
467     mCellCodes.erase(cellcode->getFQNName());
468     cellcode->changeName(newName);
469     std::pair<TKCellCodeMap::iterator, bool> r = mCellCodes.insert(TKCellCodeMap::value_type(cellcode->getFQNName(), cellcode));
470
471     return r.second;
472 }
473
474 bool DCContainer::moveCellCodeClass(DCCellCode *cellcode, const QString& pageNewContainerBasedPathName)
475 {
476     QString script = readCellCodeScriptFromFile(cellcode);
477     mCellCodes.erase(cellcode->getFQNName());
478
479     cellcode->changePath(pageNewContainerBasedPathName);
480     saveClassScriptToWorkFile(cellcode, script.toStdString());
481
482     std::pair<TKCellCodeMap::iterator, bool> r = mCellCodes.insert(TKCellCodeMap::value_type(cellcode->getFQNName(), cellcode));
483
484     return r.second;
485 }
486
487 DCVCPage* DCContainer::movePage(const QString &oldContainerBasedPathName, const QString &newContainerBasedPathName)
488 {
489     bool r = false;
490     DCVCPage *newPage = NULL;
491     DCScene *scene = getScene();
492     if (scene)
493     {
494         DCVCPage *oldPage = getScene()->getPage(oldContainerBasedPathName.toStdString());
495         newPage = getScene()->addPage(newContainerBasedPathName.toStdString());
496
497         if (oldPage && newPage)
498         {
499             r = oldPage->moveComponentsTo(newPage);
500         }
501         if (r)
502         {
503             QString sysOldFilePath = containerBasedPathToSysFilePath(oldContainerBasedPathName);
504             QString sceneSettingFilePath = scene->getSceneSettingFilePathForPage(oldPage);
505             if (!DCTreeViewWidget::removeFile(sysOldFilePath))
506             {
507                 r = false;
508             }
509             QDir dir;
510             dir.remove(sceneSettingFilePath);
511
512             if (!scene->removePage(oldPage))
513             {
514                 r = false;
515             }
516         }
517     }
518
519     return r ? newPage : NULL;
520 }
521
522
523 QList<QString> DCContainer::getAvailableCellTypes() const
524 {
525     QList<QString> list;
526
527     list.append(QString::fromStdString(TKContainer::CELLTYPE_JSBASIC));
528     list.append(QString::fromStdString(TKContainer::CELLTYPE_BASICSTORAGE));
529     list.append(QString::fromStdString(TKContainer::CELLTYPE_IN));
530     list.append(QString::fromStdString(TKContainer::CELLTYPE_OUT));
531
532     return list;
533 }
534
535 QList<QString> DCContainer::getAvailableScriptableCellTypes() const
536 {
537     QList<QString> list;
538
539     list.append(QString::fromStdString(TKContainer::CELLTYPE_JSBASIC));
540     list.append(QString::fromStdString(TKContainer::CELLTYPE_BASICSTORAGE));
541
542     return list;
543 }
544
545 bool DCContainer::getIsScriptable(const QString& type) const
546 {
547     std::string t = type.toStdString();
548
549     if (t == TKContainer::CELLTYPE_JSBASIC)
550     {
551         return true;
552     }
553     else if (t == TKContainer::CELLTYPE_BASICSTORAGE)
554     {
555         return true;
556     }
557     else if (t == TKContainer::CELLTYPE_IN)
558     {
559         return false;
560     }
561     else if (t == TKContainer::CELLTYPE_OUT)
562     {
563         return false;
564     }
565
566     return false;
567 }
568
569
570 bool DCContainer::getIsReceptorAvailable(const QString& type) const
571 {
572     std::string t = type.toStdString();
573
574     if (t == TKContainer::CELLTYPE_JSBASIC)
575     {
576         return true;
577     }
578     else if (t == TKContainer::CELLTYPE_BASICSTORAGE)
579     {
580         return true;
581     }
582     else if (t == TKContainer::CELLTYPE_IN)
583     {
584         return false;
585     }
586     else if (t == TKContainer::CELLTYPE_OUT)
587     {
588         return true;
589     }
590
591     return false;
592 }
593