1 // Copyright (c) 2012 Dennco Project
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.
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.
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/>.
17 // Created by tkawata on Sep-30, 2012.
19 #include "dccontainer.h"
22 #include "dccellcode.h"
24 #include "dcaxonterminal.h"
25 #include "dcreceptor.h"
27 #include "dccontent.h"
28 #include "dccreator.h"
29 #include "dcvpagecomponent.h"
30 #include "utils/dccomponentutil.h"
31 #include "dctreeviewwidget.h"
33 #include "DNFileList.h"
34 #include "DNDirectory.h"
35 #include "utils/dcutil.h"
37 #include <QMutexLocker>
39 #include <QDirIterator>
43 TKContainer* TKContainer::createContainer()
45 TKContainer *container = new DCContainer();
50 DCContainer::DCContainer() : d_content(NULL), d_factoryCachedLocation("")
52 d_scene = new DCScene(this);
54 d_workDirRoot = QDir::homePath() + "/.denncoCreator/work";
55 d_workDirCellRoot = d_workDirRoot + "/cells";
56 d_workDirCellCodeRoot = d_workDirRoot + "/cellcodes";
60 DCContainer::~DCContainer()
69 bool DCContainer::getIsModified() const
73 return d_scene->getIsModified();
81 bool DCContainer::isScriptableCell(DCCell *cell) const
83 bool noScript = false;
85 std::string type = cell->getType().toStdString();
87 if (type == CELLTYPE_JSBASIC || type.length() == 0)
91 else if (type == CELLTYPE_IN)
95 else if (type == CELLTYPE_OUT)
99 else if (type == CELLTYPE_BASICSTORAGE)
110 void DCContainer::setContent(DCContent *content)
115 void DCContainer::unselectCellObjectAll()
117 for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it ) {
118 DCCell *cell = dynamic_cast<DCCell*>(it->second);
120 cell->getVComponent()->setSelected(false,true);
124 QList<DCVComponent*> DCContainer::getSelectedCellObjects() const
126 QList<DCVComponent*> list;
128 for ( TKCellMap::const_iterator it = mCells.begin(); it != mCells.end(); ++it ) {
129 DCCell *cell = dynamic_cast<DCCell*>(it->second);
132 DCVComponent *object = NULL;
134 object = cell->getVComponent();
135 if (object && object->getIsSelected())
137 list.push_back(object);
141 DCAxon *axon = cell->getAxon();
142 object = axon->getVComponent();
143 if (object && object->getIsSelected())
145 list.push_back(object);
149 int n = axon->getNumberOfTerminals();
150 for (int i = 0; i < n; i++)
152 object = axon->getTerminalAt(i)->getVComponent();
153 if (object && object->getIsSelected())
155 list.push_back(object);
160 const TKReceptorMap *receptors = cell->getReceptors();
161 TKReceptorMap::const_iterator it = receptors->begin();
162 while( it != receptors->end())
164 object = ((DCReceptor*)(*it).second)->getVComponent();
165 if (object && object->getIsSelected())
167 list.push_back(object);
177 TKCell* DCContainer::addCell(std::string theLocation, std::string theName, std::string type, std::string customScript)
179 QMutexLocker(d_scene->getSceneLock());
181 DCCell *cell = dynamic_cast<DCCell*>(TKContainer::addCell(theLocation, theName, type, customScript));
183 saveCustomScriptToWorkFile(cell, customScript);
188 TKCell* DCContainer::addCell(std::string theLocation, std::string theName, TKCellCode *cellCode, std::string customScript)
190 QMutexLocker(d_scene->getSceneLock());
192 DCCell *cell = dynamic_cast<DCCell*>(TKContainer::addCell(theLocation, theName, cellCode, customScript));
194 saveCustomScriptToWorkFile(cell, customScript);
199 TKCellCode* DCContainer::addCellCode(std::string theName, std::string theAPIType, std::string code)
201 QMutexLocker(d_scene->getSceneLock());
203 DCCellCode *cellCode = dynamic_cast<DCCellCode*>(TKContainer::addCellCode(theName, theAPIType, code));
205 saveClassScriptToWorkFile(cellCode, code);
210 TKCell* DCContainer::cellFactory(std::string location, std::string name, std::string type, bool canInterfaceIn, bool canInterfaceOut)
212 if (location != d_factoryCachedLocation || d_factoryCachedPageObject.ref() == NULL)
214 d_factoryCachedPageObject.assign(d_scene->getPage(location));
215 if (d_factoryCachedPageObject.ref() == NULL)
217 d_factoryCachedPageObject.assign(d_scene->addPage(location));
220 d_factoryCachedLocation = location;
222 TKCell *cell = DCComponentUtil::createCell(this, dynamic_cast<DCVCPage*>(d_factoryCachedPageObject.ref()), location, name, type, canInterfaceIn, canInterfaceOut);
228 TKAxon* DCContainer::axonFactory(TKCell *theOwner)
230 return DCComponentUtil::createAxon((DCCell*)theOwner);
233 TKReceptor* DCContainer::receptorFactory(TKCell *theOwner)
235 return DCComponentUtil::createReceptor((DCCell*)theOwner);
238 TKAxonTerminal* DCContainer::axonTerminalFactory(TKAxon *theOwner)
240 return DCComponentUtil::createAxonTerminal((DCAxon*)theOwner);
243 TKCellCode* DCContainer::cellCodeFactory(std::string name, std::string cellapi, std::string code)
245 DCVCPage *page = NULL;
246 if (name != TKContainer::CELLCODENAME_EMPTY)
248 std::string location = name;
249 if (location.find("#") != std::string::npos)
251 location = location.substr(0, location.find("#"));
253 if (location != d_factoryCachedLocation || d_factoryCachedPageObject.ref() == NULL)
255 d_factoryCachedPageObject.assign(d_scene->getPage(location));
256 if (d_factoryCachedPageObject.ref() == NULL)
258 d_factoryCachedPageObject.assign(d_scene->addPage(location));
261 d_factoryCachedLocation = location;
262 page = dynamic_cast<DCVCPage*>(d_factoryCachedPageObject.ref());
264 return DCComponentUtil::createCellCode(this, page, name, cellapi);
267 void DCContainer::beganParsePage(const char *docRoot, const char *path)
271 QDir workCellDir(d_workDirCellRoot + QString::fromLocal8Bit(path));
272 QDir workCellCodeDir(d_workDirCellCodeRoot + QString::fromLocal8Bit(path));
273 if (!workCellDir.exists())
275 workCellDir.mkpath(workCellDir.absolutePath());
277 if (!workCellCodeDir.exists())
279 workCellCodeDir.mkpath(workCellCodeDir.absolutePath());
282 std::string location = path;
283 d_factoryCachedPageObject.assign(d_scene->getPage(location));
284 if (d_factoryCachedPageObject.ref() == NULL)
286 d_factoryCachedPageObject.assign(d_scene->addPage(location));
288 d_factoryCachedLocation = location;
291 void DCContainer::endedParsePage(const char *docRoot, const char *path)
293 (void)docRoot; (void)path;
297 void DCContainer::beganBuildContainer()
299 DCUtil::removeDirRecursive(d_workDirRoot);
302 void DCContainer::endedBuildContainer()
308 bool DCContainer::removeCellCode(DCCellCode *cellcode)
310 for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it )
312 DCCell *cell = dynamic_cast<DCCell*>(it->second);
313 if (cell->getCellCode() == cellcode)
315 cell->setCellCode(mEmptyCellClass, cell->getCustomScript().toLocal8Bit().data());
320 for ( TKCellCodeMap::iterator it = mCellCodes.begin(); it != mCellCodes.end(); ++it )
322 if (it->second == cellcode)
324 mCellCodes.erase(it);
330 if (cellcode->getPageBelonging())
332 cellcode->getPageBelonging()->unregisterCellCodeClass(cellcode->getVComponent());
339 bool DCContainer::removeCell(DCCell *cell)
341 for ( TKCellMap::iterator it = mCells.begin(); it != mCells.end(); ++it )
343 if (it->second == cell)
346 if (cell->getPageBelonging())
348 cell->getPageBelonging()->unregisterCell(cell->getVComponent());
357 bool DCContainer::saveCustomScriptToWorkFile(const DCCell *cell, std::string customScript)
359 QFile workfile(getWorkFilePathForCustomScript(cell));
360 QFileInfo fileInfo(workfile);
361 if (!fileInfo.absoluteDir().exists())
364 dir.mkpath(fileInfo.absolutePath());
367 workfile.open(QIODevice::WriteOnly);
368 QTextStream out(&workfile);
369 out << QString::fromStdString(customScript);
374 bool DCContainer::saveClassScriptToWorkFile(const DCCellCode *cellCode, std::string code)
376 QString qNamePath = QString::fromStdString(cellCode->getFQNName());
377 QString name = DCUtil::getNameFromFQNPath(qNamePath);
379 if (name.length() == 0)
382 QFile workfile(getWorkFilePathForCellCode(cellCode));
383 QFileInfo fileInfo(workfile);
384 if (!fileInfo.absoluteDir().exists())
387 dir.mkpath(fileInfo.absolutePath());
389 workfile.open(QIODevice::WriteOnly);
390 QTextStream out(&workfile);
391 out << QString::fromStdString(code);
396 QString DCContainer::readCustomScriptFromWorkFile(const DCCell *cell)
398 QFile file(getWorkFilePathForCustomScript(cell));
405 file.open(QIODevice::ReadOnly);
406 QTextStream in(&file);
407 QString out = in.readAll();
413 QString DCContainer::readCellCodeScriptFromFile(const DCCellCode *cellCode)
415 QString qNamePath = QString::fromStdString(cellCode->getFQNName());
416 QString name = DCUtil::getNameFromFQNPath(qNamePath);
418 if (name.length() == 0)
421 QFile file(getWorkFilePathForCellCode(cellCode));
427 file.open(QIODevice::ReadOnly);
428 QTextStream in(&file);
429 QString out = in.readAll();
435 QString DCContainer::sysFilePathToContainerBasedPath(const QString &sysFilePath)
437 QString containerPath = QString::fromStdString(getContainerRootPath());
438 return "/" + QDir(containerPath).relativeFilePath(sysFilePath);
441 QString DCContainer::containerBasedPathToSysFilePath(const QString &containerBasedPath)
443 QString containerPath = QString::fromStdString(getContainerRootPath());
444 return containerPath + containerBasedPath;
447 bool DCContainer::renameCell(DCCell *cell, const QString &newName)
449 QString oldFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
450 QString oldName = QString::fromStdString(cell->getName());
452 if (oldName == newName)
455 QString customScript = readCustomScriptFromWorkFile(cell);
456 QFile workFileOld(getWorkFilePathForCustomScript(cell));
458 cell->changeName(newName);
459 if (!saveCustomScriptToWorkFile(cell, customScript.toStdString()))
461 cell->changeName(oldName);
464 workFileOld.remove();
465 mCells.erase(oldFqnName.toStdString());
467 QString newFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
468 std::pair<TKCellMap::iterator, bool> r = mCells.insert(TKCellMap::value_type(newFqnName.toStdString(), cell));
473 bool DCContainer::moveCell(DCCell *cell, const QString& pageNewContainerBasedPathName)
475 QString oldFqnName = DCUtil::getFQNPath(cell->getLocation(), cell->getName());
476 QString oldContainerPath = QString::fromStdString(cell->getLocation());
478 if (oldContainerPath == pageNewContainerBasedPathName)
481 QString customScript = readCustomScriptFromWorkFile(cell);
482 QFile workFileOld(getWorkFilePathForCustomScript(cell));
484 cell->changePath(pageNewContainerBasedPathName);
485 if (!saveCustomScriptToWorkFile(cell, customScript.toStdString()))
487 cell->changePath(oldContainerPath);
490 workFileOld.remove();
491 mCells.erase(oldFqnName.toStdString());
493 QString newFqnName = DCUtil::getFQNPath(pageNewContainerBasedPathName.toStdString(), cell->getName());
494 std::pair<TKCellMap::iterator, bool> r = mCells.insert(TKCellMap::value_type(newFqnName.toStdString(), cell));
498 bool DCContainer::renameCellCodeClass(DCCellCode *cellcode, const QString &newName)
500 QString oldFqnName = QString::fromStdString(cellcode->getFQNName());
501 QString oldPath = DCUtil::getContainerBasedPathFromFQNPath(oldFqnName);
502 QString oldName = DCUtil::getNameFromFQNPath(oldFqnName);
504 if (oldName == newName)
507 QFile oldFile(getWorkFilePathForCellCode(cellcode));
508 QString script = readCellCodeScriptFromFile(cellcode);
510 cellcode->changeName(newName);
511 if (!saveClassScriptToWorkFile(cellcode, script.toStdString()))
513 cellcode->changeName(oldName);
517 mCellCodes.erase(oldFqnName.toStdString());
519 std::pair<TKCellCodeMap::iterator, bool> r = mCellCodes.insert(TKCellCodeMap::value_type(cellcode->getFQNName(), cellcode));
524 bool DCContainer::moveCellCodeClass(DCCellCode *cellcode, const QString& pageNewContainerBasedPathName)
526 QString oldFqnName = QString::fromStdString(cellcode->getFQNName());
527 QString oldPath = DCUtil::getContainerBasedPathFromFQNPath(oldFqnName);
528 QString oldName = DCUtil::getNameFromFQNPath(oldFqnName);
530 if (oldPath == pageNewContainerBasedPathName)
533 QFile oldFile(getWorkFilePathForCellCode(cellcode));
534 QString script = readCellCodeScriptFromFile(cellcode);
536 cellcode->changePath(pageNewContainerBasedPathName);
537 if (!saveClassScriptToWorkFile(cellcode, script.toStdString()))
539 cellcode->changePath(oldPath);
543 mCellCodes.erase(oldFqnName.toStdString());
545 std::pair<TKCellCodeMap::iterator, bool> r = mCellCodes.insert(TKCellCodeMap::value_type(cellcode->getFQNName(), cellcode));
550 DCVCPage* DCContainer::movePage(const QString &oldContainerBasedPathName, const QString &newContainerBasedPathName)
553 DCVCPage *newPage = NULL;
554 DCScene *scene = getScene();
557 DCVCPage *oldPage = getScene()->getPage(oldContainerBasedPathName.toStdString());
558 newPage = getScene()->addPage(newContainerBasedPathName.toStdString());
560 if (oldPage && newPage)
562 r = oldPage->moveComponentsTo(newPage);
566 QString sysOldFilePath = containerBasedPathToSysFilePath(oldContainerBasedPathName);
567 QString sceneSettingFilePath = scene->getSceneSettingFilePathForPage(oldPage);
568 if (!DCTreeViewWidget::removeFile(sysOldFilePath))
573 dir.remove(sceneSettingFilePath);
575 if (!scene->removePage(oldPage))
582 return r ? newPage : NULL;
586 QList<QString> DCContainer::getAvailableCellTypes() const
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));
598 QList<QString> DCContainer::getAvailableScriptableCellTypes() const
602 list.append(QString::fromStdString(TKContainer::CELLTYPE_JSBASIC));
603 list.append(QString::fromStdString(TKContainer::CELLTYPE_BASICSTORAGE));
608 bool DCContainer::getIsScriptable(const QString& type) const
610 std::string t = type.toStdString();
612 if (t == TKContainer::CELLTYPE_JSBASIC)
616 else if (t == TKContainer::CELLTYPE_BASICSTORAGE)
620 else if (t == TKContainer::CELLTYPE_IN)
624 else if (t == TKContainer::CELLTYPE_OUT)
633 bool DCContainer::getIsReceptorAvailable(const QString& type) const
635 std::string t = type.toStdString();
637 if (t == TKContainer::CELLTYPE_JSBASIC)
641 else if (t == TKContainer::CELLTYPE_BASICSTORAGE)
645 else if (t == TKContainer::CELLTYPE_IN)
649 else if (t == TKContainer::CELLTYPE_OUT)
657 QString DCContainer::getWorkFilePathForCustomScript(const DCCell *cell) const
659 QDir workdir(d_workDirCellRoot + QString::fromStdString(cell->getLocation()));
660 return workdir.absoluteFilePath(QString::fromStdString(cell->getName()) + ".js");
663 QString DCContainer::getWorkFilePathForCellCode(const DCCellCode *cellCode) const
665 QString qNamePath = QString::fromStdString(cellCode->getFQNName());
666 QString path = DCUtil::getContainerBasedPathFromFQNPath(qNamePath);
667 QString name = DCUtil::getNameFromFQNPath(qNamePath);
669 QDir workdir(d_workDirCellCodeRoot + path);
670 return workdir.absoluteFilePath(name + ".js");