OSDN Git Service

3eabf2491e1d7a8283ff759230a58e7ffac84b37
[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) const
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 canInterfaceIn, bool canInterfaceOut)
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, canInterfaceIn, canInterfaceOut);
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     (void)docRoot;
270
271     QDir workCellDir(d_workDirCellRoot + QString::fromLocal8Bit(path));
272     QDir workCellCodeDir(d_workDirCellCodeRoot + QString::fromLocal8Bit(path));
273     if (!workCellDir.exists())
274     {
275         workCellDir.mkpath(workCellDir.absolutePath());
276     }
277     if (!workCellCodeDir.exists())
278     {
279         workCellCodeDir.mkpath(workCellCodeDir.absolutePath());
280     }
281
282     std::string location = path;
283     d_factoryCachedPageObject.assign(d_scene->getPage(location));
284     if (d_factoryCachedPageObject.ref() == NULL)
285     {
286         d_factoryCachedPageObject.assign(d_scene->addPage(location));
287     }
288     d_factoryCachedLocation = location;
289 }
290
291 void DCContainer::endedParsePage(const char *docRoot, const char *path)
292 {
293     (void)docRoot; (void)path;
294 }
295
296
297 void DCContainer::beganBuildContainer()
298 {
299     DCUtil::removeDirRecursive(d_workDirRoot);
300 }
301
302 void DCContainer::endedBuildContainer()
303 {
304
305
306 }
307
308 bool DCContainer::removeCellCode(DCCellCode *cellcode)
309 {
310     for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it )
311     {
312         DCCell *cell = dynamic_cast<DCCell*>(it->second);
313         if (cell->getCellCode() == cellcode)
314         {
315             cell->setCellCode(mEmptyCellClass, cell->getCustomScript().toLocal8Bit().data());
316         }
317     }
318
319     bool found = false;
320     for ( TKCellCodeMap::iterator it = mCellCodes.begin(); it != mCellCodes.end(); ++it )
321     {
322         if (it->second == cellcode)
323         {
324             mCellCodes.erase(it);
325             found = true;
326             break;
327         }
328     }
329
330     if (cellcode->getPageBelonging())
331     {
332         cellcode->getPageBelonging()->unregisterCellCodeClass(cellcode->getVComponent());
333     }
334     delete cellcode;
335
336     return found;
337 }
338
339 bool DCContainer::removeCell(DCCell *cell)
340 {
341     for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it )
342     {
343         if (it->second == cell)
344         {
345             mCells.erase(it++);
346             if (cell->getPageBelonging())
347             {
348                 cell->getPageBelonging()->unregisterCell(cell->getVComponent());
349             }
350             delete cell;
351             return true;
352         }
353     }
354     return false;
355 }
356
357 bool DCContainer::saveCustomScriptToWorkFile(const DCCell *cell, std::string customScript)
358 {
359     QFile workfile(getWorkFilePathForCustomScript(cell));
360     QFileInfo fileInfo(workfile);
361     if (!fileInfo.absoluteDir().exists())
362     {
363         QDir dir;
364         dir.mkpath(fileInfo.absolutePath());
365     }
366
367     workfile.open(QIODevice::WriteOnly);
368     QTextStream out(&workfile);
369     out << QString::fromStdString(customScript);
370     workfile.close();
371     return true;
372 }
373
374 bool DCContainer::saveClassScriptToWorkFile(const DCCellCode *cellCode, std::string code)
375 {
376     QString qNamePath = QString::fromStdString(cellCode->getFQNName());
377     QString name = DCUtil::getNameFromFQNPath(qNamePath);
378
379     if (name.length() == 0)
380         return false;
381
382     QFile workfile(getWorkFilePathForCellCode(cellCode));
383     QFileInfo fileInfo(workfile);
384     if (!fileInfo.absoluteDir().exists())
385     {
386         QDir dir;
387         dir.mkpath(fileInfo.absolutePath());
388     }
389     workfile.open(QIODevice::WriteOnly);
390     QTextStream out(&workfile);
391     out << QString::fromStdString(code);
392     workfile.close();
393     return true;
394 }
395
396 QString DCContainer::readCustomScriptFromWorkFile(const DCCell *cell)
397 {
398     QFile file(getWorkFilePathForCustomScript(cell));
399
400     if (!file.exists())
401     {
402         return "";
403     }
404
405     file.open(QIODevice::ReadOnly);
406     QTextStream in(&file);
407     QString out = in.readAll();
408     file.close();
409
410     return out;
411 }
412
413 QString DCContainer::readCellCodeScriptFromFile(const DCCellCode *cellCode)
414 {
415     QString qNamePath = QString::fromStdString(cellCode->getFQNName());
416     QString name = DCUtil::getNameFromFQNPath(qNamePath);
417
418     if (name.length() == 0)
419         return false;
420
421     QFile file(getWorkFilePathForCellCode(cellCode));
422     if (!file.exists())
423     {
424         return "";
425     }
426
427     file.open(QIODevice::ReadOnly);
428     QTextStream in(&file);
429     QString out = in.readAll();
430     file.close();
431
432     return out;
433 }
434
435 QString DCContainer::sysFilePathToContainerBasedPath(const QString &sysFilePath)
436 {
437     QString containerPath = QString::fromStdString(getContainerRootPath());
438     return "/" + QDir(containerPath).relativeFilePath(sysFilePath);
439 }
440
441 QString DCContainer::containerBasedPathToSysFilePath(const QString &containerBasedPath)
442 {
443     QString containerPath = QString::fromStdString(getContainerRootPath());
444     return containerPath + containerBasedPath;
445 }
446
447 bool DCContainer::renameCell(DCCell *cell, const QString &newName)
448 {
449     QString oldFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
450     QString oldName = QString::fromStdString(cell->getName());
451
452     if (oldName == newName)
453         return true;
454
455     QString customScript = readCustomScriptFromWorkFile(cell);
456     QFile workFileOld(getWorkFilePathForCustomScript(cell));
457
458     cell->changeName(newName);
459     if (!saveCustomScriptToWorkFile(cell, customScript.toStdString()))
460     {
461         cell->changeName(oldName);
462         return false;
463     }
464     workFileOld.remove();
465     mCells.erase(oldFqnName.toStdString());
466
467     QString newFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
468     std::pair<TKCellMap::iterator, bool> r = mCells.insert(TKCellMap::value_type(newFqnName.toStdString(), cell));
469
470     return r.second;
471 }
472
473 bool DCContainer::moveCell(DCCell *cell, const QString& pageNewContainerBasedPathName)
474 {
475     QString oldFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
476     QString oldContainerPath = QString::fromStdString(cell->getLocation());
477
478     if (oldContainerPath == pageNewContainerBasedPathName)
479         return true;
480
481     QString customScript = readCustomScriptFromWorkFile(cell);
482     QFile workFileOld(getWorkFilePathForCustomScript(cell));
483
484     cell->changePath(pageNewContainerBasedPathName);
485     if (!saveCustomScriptToWorkFile(cell, customScript.toStdString()))
486     {
487         cell->changePath(oldContainerPath);
488         return false;
489     }
490     workFileOld.remove();
491     mCells.erase(oldFqnName.toStdString());
492
493     QString newFqnName = DCUtil::getFQNPath(pageNewContainerBasedPathName.toStdString(), cell->getName());
494     std::pair<TKCellMap::iterator, bool> r = mCells.insert(TKCellMap::value_type(newFqnName.toStdString(), cell));
495     return r.second;
496 }
497
498 bool DCContainer::renameCellCodeClass(DCCellCode *cellcode, const QString &newName)
499 {
500     QString oldFqnName = QString::fromStdString(cellcode->getFQNName());
501     QString oldPath = DCUtil::getContainerBasedPathFromFQNPath(oldFqnName);
502     QString oldName = DCUtil::getNameFromFQNPath(oldFqnName);
503
504     if (oldName == newName)
505         return true;
506
507     QFile oldFile(getWorkFilePathForCellCode(cellcode));
508     QString script = readCellCodeScriptFromFile(cellcode);
509
510     cellcode->changeName(newName);
511     if (!saveClassScriptToWorkFile(cellcode, script.toStdString()))
512     {
513         cellcode->changeName(oldName);
514         return false;
515     }
516     oldFile.remove();
517     mCellCodes.erase(oldFqnName.toStdString());
518
519     std::pair<TKCellCodeMap::iterator, bool> r = mCellCodes.insert(TKCellCodeMap::value_type(cellcode->getFQNName(), cellcode));
520
521     return r.second;
522 }
523
524 bool DCContainer::moveCellCodeClass(DCCellCode *cellcode, const QString& pageNewContainerBasedPathName)
525 {
526     QString oldFqnName = QString::fromStdString(cellcode->getFQNName());
527     QString oldPath = DCUtil::getContainerBasedPathFromFQNPath(oldFqnName);
528     QString oldName = DCUtil::getNameFromFQNPath(oldFqnName);
529
530     if (oldPath == pageNewContainerBasedPathName)
531         return true;
532
533     QFile oldFile(getWorkFilePathForCellCode(cellcode));
534     QString script = readCellCodeScriptFromFile(cellcode);
535
536     cellcode->changePath(pageNewContainerBasedPathName);
537     if (!saveClassScriptToWorkFile(cellcode, script.toStdString()))
538     {
539         cellcode->changePath(oldPath);
540         return false;
541     }
542     oldFile.remove();
543     mCellCodes.erase(oldFqnName.toStdString());
544
545     std::pair<TKCellCodeMap::iterator, bool> r = mCellCodes.insert(TKCellCodeMap::value_type(cellcode->getFQNName(), cellcode));
546
547     return r.second;
548 }
549
550 DCVCPage* DCContainer::movePage(const QString &oldContainerBasedPathName, const QString &newContainerBasedPathName)
551 {
552     bool r = false;
553     DCVCPage *newPage = NULL;
554     DCScene *scene = getScene();
555     if (scene)
556     {
557         DCVCPage *oldPage = getScene()->getPage(oldContainerBasedPathName.toStdString());
558         newPage = getScene()->addPage(newContainerBasedPathName.toStdString());
559
560         if (oldPage && newPage)
561         {
562             r = oldPage->moveComponentsTo(newPage);
563         }
564         if (r)
565         {
566             QString sysOldFilePath = containerBasedPathToSysFilePath(oldContainerBasedPathName);
567             QString sceneSettingFilePath = scene->getSceneSettingFilePathForPage(oldPage);
568             if (!DCTreeViewWidget::removeFile(sysOldFilePath))
569             {
570                 r = false;
571             }
572             QDir dir;
573             dir.remove(sceneSettingFilePath);
574
575             if (!scene->removePage(oldPage))
576             {
577                 r = false;
578             }
579         }
580     }
581
582     return r ? newPage : NULL;
583 }
584
585
586 QList<QString> DCContainer::getAvailableCellTypes() const
587 {
588     QList<QString> list;
589
590     list.append(QString::fromStdString(TKContainer::CELLTYPE_JSBASIC));
591     list.append(QString::fromStdString(TKContainer::CELLTYPE_BASICSTORAGE));
592     list.append(QString::fromStdString(TKContainer::CELLTYPE_IN));
593     list.append(QString::fromStdString(TKContainer::CELLTYPE_OUT));
594
595     return list;
596 }
597
598 QList<QString> DCContainer::getAvailableScriptableCellTypes() const
599 {
600     QList<QString> list;
601
602     list.append(QString::fromStdString(TKContainer::CELLTYPE_JSBASIC));
603     list.append(QString::fromStdString(TKContainer::CELLTYPE_BASICSTORAGE));
604
605     return list;
606 }
607
608 bool DCContainer::getIsScriptable(const QString& type) const
609 {
610     std::string t = type.toStdString();
611
612     if (t == TKContainer::CELLTYPE_JSBASIC)
613     {
614         return true;
615     }
616     else if (t == TKContainer::CELLTYPE_BASICSTORAGE)
617     {
618         return true;
619     }
620     else if (t == TKContainer::CELLTYPE_IN)
621     {
622         return false;
623     }
624     else if (t == TKContainer::CELLTYPE_OUT)
625     {
626         return false;
627     }
628
629     return false;
630 }
631
632
633 bool DCContainer::getIsReceptorAvailable(const QString& type) const
634 {
635     std::string t = type.toStdString();
636
637     if (t == TKContainer::CELLTYPE_JSBASIC)
638     {
639         return true;
640     }
641     else if (t == TKContainer::CELLTYPE_BASICSTORAGE)
642     {
643         return true;
644     }
645     else if (t == TKContainer::CELLTYPE_IN)
646     {
647         return false;
648     }
649     else if (t == TKContainer::CELLTYPE_OUT)
650     {
651         return true;
652     }
653
654     return false;
655 }
656
657 QString DCContainer::getWorkFilePathForCustomScript(const DCCell *cell) const
658 {
659     QDir workdir(d_workDirCellRoot + QString::fromStdString(cell->getLocation()));
660     return workdir.absoluteFilePath(QString::fromStdString(cell->getName()) + ".js");
661 }
662
663 QString DCContainer::getWorkFilePathForCellCode(const DCCellCode *cellCode) const
664 {
665     QString qNamePath = QString::fromStdString(cellCode->getFQNName());
666     QString path = DCUtil::getContainerBasedPathFromFQNPath(qNamePath);
667     QString name = DCUtil::getNameFromFQNPath(qNamePath);
668
669     QDir workdir(d_workDirCellCodeRoot + path);
670     return workdir.absoluteFilePath(name + ".js");
671 }