diff --git a/src/adaptors/UBImportDocument.cpp b/src/adaptors/UBImportDocument.cpp index 3e7808cf..6a689b76 100644 --- a/src/adaptors/UBImportDocument.cpp +++ b/src/adaptors/UBImportDocument.cpp @@ -1,217 +1,219 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "UBImportDocument.h" -#include "document/UBDocumentProxy.h" - -#include "frameworks/UBFileSystemUtils.h" - -#include "core/UBApplication.h" -#include "core/UBSettings.h" -#include "core/UBPersistenceManager.h" - -#include "globals/UBGlobals.h" - -THIRD_PARTY_WARNINGS_DISABLE -#include "quazip.h" -#include "quazipfile.h" -#include "quazipfileinfo.h" -THIRD_PARTY_WARNINGS_ENABLE - -#include "core/memcheck.h" - -UBImportDocument::UBImportDocument(QObject *parent) - :UBImportAdaptor(parent) -{ - // NOOP -} - -UBImportDocument::~UBImportDocument() -{ - // NOOP -} - - -QStringList UBImportDocument::supportedExtentions() -{ - return QStringList("ubz"); -} - - -QString UBImportDocument::importFileFilter() -{ - return tr("Open-Sankore (*.ubz)"); -} - - -QString UBImportDocument::expandFileToDir(const QFile& pZipFile, const QString& pDir) -{ - - QDir rootDir(pDir); - QuaZip zip(pZipFile.fileName()); - - if(!zip.open(QuaZip::mdUnzip)) - { - qWarning() << "Import failed. Cause zip.open(): " << zip.getZipError(); - return ""; - } - - zip.setFileNameCodec("UTF-8"); - QuaZipFileInfo info; - QuaZipFile file(&zip); - - // TODO UB 4.x implement a mechanism that can replace an existing - // document based on the UID of the document. - bool createNewDocument = true; - QString documentRootFolder; - - // first we search the metadata.rdf to check the document properties - for(bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) - { - if(!zip.getCurrentFileInfo(&info)) - { - qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError(); - return ""; - } - - QFileInfo currentFileInfo(pDir + "/" + file.getActualFileName()); - } - - if (createNewDocument) - documentRootFolder = UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath(); - - - QFile out; - char c; - for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) - { - if(!zip.getCurrentFileInfo(&info)) - { - //TOD UB 4.3 O display error to user or use crash reporter - qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError(); - return ""; - } - - if(!file.open(QIODevice::ReadOnly)) - { - qWarning() << "Import failed. Cause: file.open(): " << zip.getZipError(); - return ""; - } - - if(file.getZipError()!= UNZ_OK) - { - qWarning() << "Import failed. Cause: file.getFileName(): " << zip.getZipError(); - return ""; - } - - QString newFileName = documentRootFolder + "/" + file.getActualFileName(); - QFileInfo newFileInfo(newFileName); - rootDir.mkpath(newFileInfo.absolutePath()); - - out.setFileName(newFileName); - out.open(QIODevice::WriteOnly); - - // Slow like hell (on GNU/Linux at least), but it is not my fault. - // Not ZIP/UNZIP package's fault either. - // The slowest thing here is out.putChar(c). - QByteArray outFileContent = file.readAll(); - if (out.write(outFileContent) == -1) - { - qWarning() << "Import failed. Cause: Unable to write file"; - out.close(); - return ""; - } - - while(file.getChar(&c)) - out.putChar(c); - - out.close(); - - if(file.getZipError()!=UNZ_OK) - { - qWarning() << "Import failed. Cause: " << zip.getZipError(); - return ""; - } - - if(!file.atEnd()) - { - qWarning() << "Import failed. Cause: read all but not EOF"; - return ""; - } - - file.close(); - - if(file.getZipError()!=UNZ_OK) - { - qWarning() << "Import failed. Cause: file.close(): " << file.getZipError(); - return ""; - } - - } - - zip.close(); - - if(zip.getZipError()!=UNZ_OK) - { - qWarning() << "Import failed. Cause: zip.close(): " << zip.getZipError(); - return ""; - } - - - return documentRootFolder; -} - - -UBDocumentProxy* UBImportDocument::importFile(const QFile& pFile, const QString& pGroup) -{ - Q_UNUSED(pGroup); // group is defined in the imported file - - QFileInfo fi(pFile); - UBApplication::showMessage(tr("Importing file %1...").arg(fi.baseName()), true); - - // first unzip the file to the correct place - QString path = UBSettings::settings()->uniboardDocumentDirectory(); - - QString documentRootFolder = expandFileToDir(pFile, path); - - if(!documentRootFolder.length()){ - UBApplication::showMessage(tr("Import of file %1 failed.").arg(fi.baseName())); - return 0; - } - else{ - UBDocumentProxy* newDocument = UBPersistenceManager::persistenceManager()->createDocumentFromDir(documentRootFolder); - UBApplication::showMessage(tr("Import successful.")); - return newDocument; - } -} - - -bool UBImportDocument::addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile) -{ - QFileInfo fi(pFile); - UBApplication::showMessage(tr("Importing file %1...").arg(fi.baseName()), true); - - QString path = UBFileSystemUtils::createTempDir(); - - QString documentRootFolder = expandFileToDir(pFile, path); - - UBPersistenceManager::persistenceManager()->addDirectoryContentToDocument(documentRootFolder, pDocument); - - UBFileSystemUtils::deleteDir(path); - - UBApplication::showMessage(tr("Import successful.")); - - return true; -} +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "UBImportDocument.h" +#include "document/UBDocumentProxy.h" + +#include "frameworks/UBFileSystemUtils.h" + +#include "core/UBApplication.h" +#include "core/UBSettings.h" +#include "core/UBPersistenceManager.h" + +#include "globals/UBGlobals.h" + +THIRD_PARTY_WARNINGS_DISABLE +#include "quazip.h" +#include "quazipfile.h" +#include "quazipfileinfo.h" +THIRD_PARTY_WARNINGS_ENABLE + +#include "core/memcheck.h" + +UBImportDocument::UBImportDocument(QObject *parent) + :UBImportAdaptor(parent) +{ + // NOOP +} + +UBImportDocument::~UBImportDocument() +{ + // NOOP +} + + +QStringList UBImportDocument::supportedExtentions() +{ + return QStringList("ubz"); +} + + +QString UBImportDocument::importFileFilter() +{ + return tr("Open-Sankore (*.ubz)"); +} + + +QString UBImportDocument::expandFileToDir(const QFile& pZipFile, const QString& pDir) +{ + + QDir rootDir(pDir); + QuaZip zip(pZipFile.fileName()); + + if(!zip.open(QuaZip::mdUnzip)) + { + qWarning() << "Import failed. Cause zip.open(): " << zip.getZipError(); + return ""; + } + + zip.setFileNameCodec("UTF-8"); + QuaZipFileInfo info; + QuaZipFile file(&zip); + + // TODO UB 4.x implement a mechanism that can replace an existing + // document based on the UID of the document. + bool createNewDocument = true; + QString documentRootFolder; + + // first we search the metadata.rdf to check the document properties + for(bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) + { + if(!zip.getCurrentFileInfo(&info)) + { + qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError(); + return ""; + } + + QFileInfo currentFileInfo(pDir + "/" + file.getActualFileName()); + } + + if (createNewDocument) + documentRootFolder = UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath(); + + + QFile out; + char c; + for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) + { + if(!zip.getCurrentFileInfo(&info)) + { + //TOD UB 4.3 O display error to user or use crash reporter + qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError(); + return ""; + } + + if(!file.open(QIODevice::ReadOnly)) + { + qWarning() << "Import failed. Cause: file.open(): " << zip.getZipError(); + return ""; + } + + if(file.getZipError()!= UNZ_OK) + { + qWarning() << "Import failed. Cause: file.getFileName(): " << zip.getZipError(); + return ""; + } + + QString newFileName = documentRootFolder + "/" + file.getActualFileName(); + QFileInfo newFileInfo(newFileName); + rootDir.mkpath(newFileInfo.absolutePath()); + + out.setFileName(newFileName); + out.open(QIODevice::WriteOnly); + + // Slow like hell (on GNU/Linux at least), but it is not my fault. + // Not ZIP/UNZIP package's fault either. + // The slowest thing here is out.putChar(c). + QByteArray outFileContent = file.readAll(); + if (out.write(outFileContent) == -1) + { + qWarning() << "Import failed. Cause: Unable to write file"; + out.close(); + return ""; + } + + while(file.getChar(&c)) + out.putChar(c); + + out.close(); + + if(file.getZipError()!=UNZ_OK) + { + qWarning() << "Import failed. Cause: " << zip.getZipError(); + return ""; + } + + if(!file.atEnd()) + { + qWarning() << "Import failed. Cause: read all but not EOF"; + return ""; + } + + file.close(); + + if(file.getZipError()!=UNZ_OK) + { + qWarning() << "Import failed. Cause: file.close(): " << file.getZipError(); + return ""; + } + + } + + zip.close(); + + if(zip.getZipError()!=UNZ_OK) + { + qWarning() << "Import failed. Cause: zip.close(): " << zip.getZipError(); + return ""; + } + + + return documentRootFolder; +} + + +UBDocumentProxy* UBImportDocument::importFile(const QFile& pFile, const QString& pGroup) +{ + Q_UNUSED(pGroup); // group is defined in the imported file + + QFileInfo fi(pFile); + UBApplication::showMessage(tr("Importing file %1...").arg(fi.baseName()), true); + + // first unzip the file to the correct place + QString path = UBSettings::settings()->uniboardDocumentDirectory(); + + QString documentRootFolder = expandFileToDir(pFile, path); + + if(!documentRootFolder.length()){ + UBApplication::showMessage(tr("Import of file %1 failed.").arg(fi.baseName())); + return 0; + } + else{ + UBDocumentProxy* newDocument = UBPersistenceManager::persistenceManager()->createDocumentFromDir(documentRootFolder, pGroup); + + UBApplication::showMessage(tr("Import successful.")); + + return newDocument; + } +} + + +bool UBImportDocument::addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile) +{ + QFileInfo fi(pFile); + UBApplication::showMessage(tr("Importing file %1...").arg(fi.baseName()), true); + + QString path = UBFileSystemUtils::createTempDir(); + + QString documentRootFolder = expandFileToDir(pFile, path); + + UBPersistenceManager::persistenceManager()->addDirectoryContentToDocument(documentRootFolder, pDocument); + + UBFileSystemUtils::deleteDir(path); + + UBApplication::showMessage(tr("Import successful.")); + + return true; +} diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index 4e2d5d9e..2406e28e 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -1,1175 +1,1185 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "UBPersistenceManager.h" -#include "gui/UBMainWindow.h" - -#include - -#include "frameworks/UBPlatformUtils.h" -#include "frameworks/UBFileSystemUtils.h" - -#include "core/UBApplication.h" -#include "core/UBSettings.h" -#include "core/UBSetting.h" - -#include "document/UBDocumentProxy.h" - -#include "adaptors/UBExportPDF.h" -#include "adaptors/UBSvgSubsetAdaptor.h" -#include "adaptors/UBThumbnailAdaptor.h" -#include "adaptors/UBMetadataDcSubsetAdaptor.h" - -#include "core/memcheck.h" - -const QString UBPersistenceManager::imageDirectory = "images"; // added to UBPersistenceManager::mAllDirectories -const QString UBPersistenceManager::objectDirectory = "objects"; // added to UBPersistenceManager::mAllDirectories -const QString UBPersistenceManager::widgetDirectory = "widgets"; // added to UBPersistenceManager::mAllDirectories -const QString UBPersistenceManager::videoDirectory = "videos"; // added to UBPersistenceManager::mAllDirectories -const QString UBPersistenceManager::audioDirectory = "audios"; // added to - -UBPersistenceManager * UBPersistenceManager::sSingleton = 0; - -UBPersistenceManager::UBPersistenceManager(QObject *pParent) - : QObject(pParent) - , mHasPurgedDocuments(false) -{ - - mDocumentSubDirectories << imageDirectory; - mDocumentSubDirectories << objectDirectory; - mDocumentSubDirectories << widgetDirectory; - mDocumentSubDirectories << videoDirectory; - mDocumentSubDirectories << audioDirectory; - - documentProxies = allDocumentProxies(); - emit proxyListChanged(); -} - -UBPersistenceManager* UBPersistenceManager::persistenceManager() -{ - if (!sSingleton) - { - sSingleton = new UBPersistenceManager(UBApplication::staticMemoryCleaner); - } - - return sSingleton; -} - -void UBPersistenceManager::destroy() -{ - if (sSingleton) - delete sSingleton; - sSingleton = NULL; -} - -UBPersistenceManager::~UBPersistenceManager() -{ - foreach(QPointer proxyGuard, documentProxies) - { - if (!proxyGuard.isNull()) - delete proxyGuard.data(); - } -} - - -QList > UBPersistenceManager::allDocumentProxies() -{ - mDocumentRepositoryPath = UBSettings::settings()->uniboardDocumentDirectory(); - - QDir rootDir(mDocumentRepositoryPath); - rootDir.mkpath(rootDir.path()); - - - QFileSystemWatcher* watcher = new QFileSystemWatcher(this); - watcher->addPath(mDocumentRepositoryPath); - - connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(documentRepositoryChanged(const QString&))); - - QList > proxies; - - foreach(QString path, rootDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, - QDir::Time | QDir::Reversed)) - { - QString fullPath = rootDir.path() + "/" + path; - - QDir dir(fullPath); - - if (dir.entryList(QDir::Files | QDir::NoDotAndDotDot).size() > 0) - { - UBDocumentProxy* proxy = new UBDocumentProxy(fullPath); // deleted in UBPersistenceManager::destructor - - QMap metadatas = UBMetadataDcSubsetAdaptor::load(fullPath); - - foreach(QString key, metadatas.keys()) - { - proxy->setMetaData(key, metadatas.value(key)); - } - - proxy->setPageCount(sceneCount(proxy)); - - proxies << QPointer(proxy); - - } - } - - return proxies; -} - - -QStringList UBPersistenceManager::allShapes() -{ - QString shapeLibraryPath = UBSettings::settings()->uniboardShapeLibraryDirectory(); - - QDir dir(shapeLibraryPath); - - if (!dir.exists()) - dir.mkpath(shapeLibraryPath); - - QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); - QStringList paths; - - foreach(QString file, files) - { - paths.append(shapeLibraryPath + QString("/") + file); - } - - return paths; -} - -QStringList UBPersistenceManager::allGips() -{ - QString gipLibraryPath = UBSettings::settings()->uniboardGipLibraryDirectory(); - - QDir dir(gipLibraryPath); - - QStringList files = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); - QStringList paths; - - foreach(QString file, files) - { - QFileInfo fi(file); - - if (UBSettings::settings()->widgetFileExtensions.contains(fi.suffix())) - paths.append(dir.path() + QString("/") + file); - } - - return paths; -} - -QStringList UBPersistenceManager::allSounds() -{ - QString soundLibraryPath = QDesktopServices::storageLocation(QDesktopServices::MusicLocation); - - QDir dir(soundLibraryPath); - - QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); - QStringList paths; - - foreach(QString file, files) - { - QFileInfo fi(file); - paths.append(dir.path() + QString("/") + file); - } - - return paths; -} - -QStringList UBPersistenceManager::allImages(const QDir& dir) -{ - if (!dir.exists()) - dir.mkpath(dir.path()); - - QStringList files = dir.entryList(QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name); - QStringList paths; - - foreach(QString file, files) - { - paths.append(dir.path() + QString("/") + file); - } - - return paths; -} - - -QStringList UBPersistenceManager::allVideos(const QDir& dir) -{ - if (!dir.exists()) - dir.mkpath(dir.path()); - - QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); - QStringList paths; - - foreach(QString file, files) - { - paths.append(dir.path() + QString("/") + file); - } - - return paths; -} - - -QStringList UBPersistenceManager::allWidgets(const QDir& dir) -{ - if (!dir.exists()) - dir.mkpath(dir.path()); - - QStringList files = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); - QStringList paths; - - foreach(QString file, files) - { - QFileInfo fi(file); - - if (UBSettings::settings()->widgetFileExtensions.contains(fi.suffix())) - paths.append(dir.path() + QString("/") + file); - } - - return paths; -} - - -UBDocumentProxy* UBPersistenceManager::createDocument(const QString& pGroupName, const QString& pName, bool withEmptyPage) -{ - checkIfDocumentRepositoryExists(); - - UBDocumentProxy *doc = new UBDocumentProxy(); // deleted in UBPersistenceManager::destructor - - if (pGroupName.length() > 0) - { - doc->setMetaData(UBSettings::documentGroupName, pGroupName); - } - - if (pName.length() > 0) - { - doc->setMetaData(UBSettings::documentName, pName); - } - - doc->setMetaData(UBSettings::documentVersion, UBSettings::currentFileVersion); - doc->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - - if (withEmptyPage) createDocumentSceneAt(doc, 0); - - documentProxies.insert(0, QPointer(doc)); - - emit proxyListChanged(); - - emit documentCreated(doc); - - mDocumentCreatedDuringSession << doc; - - return doc; -} - - -UBDocumentProxy* UBPersistenceManager::createDocumentFromDir(const QString& pDocumentDirectory) -{ - checkIfDocumentRepositoryExists(); - - UBDocumentProxy* doc = new UBDocumentProxy(pDocumentDirectory); // deleted in UBPersistenceManager::destructor - - QMap metadatas = UBMetadataDcSubsetAdaptor::load(pDocumentDirectory); - - foreach(QString key, metadatas.keys()) - { - doc->setMetaData(key, metadatas.value(key)); - } - - doc->setUuid(QUuid::createUuid()); - doc->setPageCount(sceneCount(doc)); - - UBMetadataDcSubsetAdaptor::persist(doc); - - for(int i = 0; i < doc->pageCount(); i++) - { - UBSvgSubsetAdaptor::setSceneUuid(doc, i, QUuid::createUuid()); - } - - documentProxies << QPointer(doc); - - emit proxyListChanged(); - - emit documentCreated(doc); - - return doc; -} - - -void UBPersistenceManager::deleteDocument(UBDocumentProxy* pDocumentProxy) -{ - checkIfDocumentRepositoryExists(); - - emit documentWillBeDeleted(pDocumentProxy); - - UBFileSystemUtils::deleteDir(pDocumentProxy->persistencePath()); - - documentProxies.removeAll(QPointer(pDocumentProxy)); - mDocumentCreatedDuringSession.removeAll(pDocumentProxy); - - mSceneCache.removeAllScenes(pDocumentProxy); - - pDocumentProxy->deleteLater(); - - emit proxyListChanged(); - -} - - -UBDocumentProxy* UBPersistenceManager::duplicateDocument(UBDocumentProxy* pDocumentProxy) -{ - checkIfDocumentRepositoryExists(); - - UBDocumentProxy *copy = new UBDocumentProxy(); // deleted in UBPersistenceManager::destructor - - generatePathIfNeeded(copy); - - UBFileSystemUtils::copyDir(pDocumentProxy->persistencePath(), copy->persistencePath()); - - // regenerate scenes UUIDs - for(int i = 0; i < pDocumentProxy->pageCount(); i++) - { - UBSvgSubsetAdaptor::setSceneUuid(pDocumentProxy, i, QUuid::createUuid()); - } - - foreach(QString key, pDocumentProxy->metaDatas().keys()) - { - copy->setMetaData(key, pDocumentProxy->metaDatas().value(key)); - } - - copy->setMetaData(UBSettings::documentName, - pDocumentProxy->metaData(UBSettings::documentName).toString() + " " + tr("(copy)")); - - copy->setUuid(QUuid::createUuid()); - - persistDocumentMetadata(copy); - - copy->setPageCount(sceneCount(copy)); - - documentProxies << QPointer(copy); - - emit proxyListChanged(); - - emit documentCreated(copy); - - return copy; - -} - - -void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QList& indexes) -{ - checkIfDocumentRepositoryExists(); - - int pageCount = UBPersistenceManager::persistenceManager()->sceneCount(proxy); - - QList compactedIndexes; - - foreach(int index, indexes) - { - if (!compactedIndexes.contains(index)) - compactedIndexes.append(index); - } - - if (compactedIndexes.size() == pageCount) - { - deleteDocument(proxy); - return; - } - - if (compactedIndexes.size() == 0) - return; - - foreach(int index, compactedIndexes) - { - emit documentSceneWillBeDeleted(proxy, index); - } - - QString sourceGroupName = proxy->metaData(UBSettings::documentGroupName).toString(); - QString sourceName = proxy->metaData(UBSettings::documentName).toString(); - UBDocumentProxy *trashDocProxy = createDocument(UBSettings::trashedDocumentGroupNamePrefix + sourceGroupName, sourceName, false); - - foreach(int index, compactedIndexes) - { - UBGraphicsScene *scene = loadDocumentScene(proxy, index); - if (scene) - { - //scene is about to move into new document - foreach (QUrl relativeFile, scene->relativeDependencies()) - { - QString source = scene->document()->persistencePath() + "/" + relativeFile.toString(); - QString target = trashDocProxy->persistencePath() + "/" + relativeFile.toString(); - - QFileInfo fi(target); - QDir d = fi.dir(); - - d.mkpath(d.absolutePath()); - QFile::copy(source, target); - } - - insertDocumentSceneAt(trashDocProxy, scene, trashDocProxy->pageCount()); - } - } - - for (int i = 1; i < pageCount; i++) - { - renamePage(trashDocProxy, i , i - 1); - } - - foreach(int index, compactedIndexes) - { - QString svgFileName = proxy->persistencePath() + - UBFileSystemUtils::digitFileFormat("/page%1.svg", index + 1); - - QFile::remove(svgFileName); - - QString thumbFileName = proxy->persistencePath() + - UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", index + 1); - - QFile::remove(thumbFileName); - - mSceneCache.removeScene(proxy, index); - - proxy->decPageCount(); - - } - - qSort(compactedIndexes); - - int offset = 1; - - for (int i = compactedIndexes.at(0) + 1; i < pageCount; i++) - { - if(compactedIndexes.contains(i)) - { - offset++; - } - else - { - renamePage(proxy, i , i - offset); - - mSceneCache.moveScene(proxy, i, i - offset); - - } - } - - foreach(int index, compactedIndexes) - { - emit documentSceneDeleted(proxy, index); - } -} - - -void UBPersistenceManager::duplicateDocumentScene(UBDocumentProxy* proxy, int index) -{ - checkIfDocumentRepositoryExists(); - - int pageCount = UBPersistenceManager::persistenceManager()->sceneCount(proxy); - - for (int i = pageCount; i > index + 1; i--) - { - renamePage(proxy, i - 1 , i); - - mSceneCache.moveScene(proxy, i - 1, i); - - } - - copyPage(proxy, index , index + 1); - - proxy->incPageCount(); - - //due to architectural peculiarity we need to save teacher bar info, otherwise we'll see not exactly what we expect - sTeacherBarInfos properInfo = getTeacherBarInfos(proxy, index + 1); - //after the call below - emit documentSceneCreated(proxy, index + 1); - //restoring info - persistTeacherBar(proxy, index + 1, properInfo); -} - - -UBGraphicsScene* UBPersistenceManager::createDocumentSceneAt(UBDocumentProxy* proxy, int index) -{ - int count = sceneCount(proxy); - - for(int i = count - 1; i >= index; i--) - { - renamePage(proxy, i , i + 1); - } - - mSceneCache.shiftUpScenes(proxy, index, count -1); - - UBGraphicsScene *newScene = mSceneCache.createScene(proxy, index); - - newScene->setBackground(UBSettings::settings()->isDarkBackground(), - UBSettings::settings()->UBSettings::isCrossedBackground()); - - persistDocumentScene(proxy, newScene, index); - - proxy->incPageCount(); - - emit documentSceneCreated(proxy, index); - - return newScene; -} - - -void UBPersistenceManager::insertDocumentSceneAt(UBDocumentProxy* proxy, UBGraphicsScene* scene, int index) -{ - scene->setDocument(proxy); - - int count = sceneCount(proxy); - - for(int i = count - 1; i >= index; i--) - { - renamePage(proxy, i , i + 1); - } - - mSceneCache.shiftUpScenes(proxy, index, count -1); - - mSceneCache.insert(proxy, index, scene); - - persistDocumentScene(proxy, scene, index); - - proxy->incPageCount(); - - emit documentSceneCreated(proxy, index); - -} - - -void UBPersistenceManager::moveSceneToIndex(UBDocumentProxy* proxy, int source, int target) -{ - checkIfDocumentRepositoryExists(); - - if (source == target) - return; - - QFile svgTmp(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", source + 1)); - svgTmp.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.tmp", target + 1)); - - QFile thumbTmp(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", source + 1)); - thumbTmp.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.tmp", target + 1)); - - if (source < target) - { - for (int i = source + 1; i <= target; i++) - { - renamePage(proxy, i , i - 1); - } - } - else - { - for (int i = source - 1; i >= target; i--) - { - renamePage(proxy, i , i + 1); - } - } - - QFile svg(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.tmp", target + 1)); - svg.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", target + 1)); - - QFile thumb(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.tmp", target + 1)); - thumb.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", target + 1)); - - mSceneCache.moveScene(proxy, source, target); - - emit documentSceneMoved(proxy, target); -} - - -UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, int sceneIndex) -{ - if (mSceneCache.contains(proxy, sceneIndex)) - { - //qDebug() << "scene" << sceneIndex << "retrieved from cache ..."; - return mSceneCache.value(proxy, sceneIndex); - } - else - { - UBGraphicsScene* scene = UBSvgSubsetAdaptor::loadScene(proxy, sceneIndex); - - if (scene) - mSceneCache.insert(proxy, sceneIndex, scene); - - return scene; - } -} - - -void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* pScene, const int pSceneIndex) -{ - checkIfDocumentRepositoryExists(); - - pScene->deselectAllItems(); - - generatePathIfNeeded(pDocumentProxy); - - QDir dir(pDocumentProxy->persistencePath()); - dir.mkpath(pDocumentProxy->persistencePath()); - - if (pDocumentProxy->isModified()) - UBMetadataDcSubsetAdaptor::persist(pDocumentProxy); - - if (pScene->isModified()) - { - UBThumbnailAdaptor::persistScene(pDocumentProxy->persistencePath(), pScene, pSceneIndex); - - UBSvgSubsetAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex); - - pScene->setModified(false); - } - - mSceneCache.insert(pDocumentProxy, pSceneIndex, pScene); - - emit documentCommitted(pDocumentProxy); - -} - - -UBDocumentProxy* UBPersistenceManager::persistDocumentMetadata(UBDocumentProxy* pDocumentProxy) -{ - UBMetadataDcSubsetAdaptor::persist(pDocumentProxy); - - emit documentMetadataChanged(pDocumentProxy); - - return pDocumentProxy; -} - - -void UBPersistenceManager::renamePage(UBDocumentProxy* pDocumentProxy, const int sourceIndex, const int targetIndex) -{ - QFile svg(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex + 1)); - svg.rename(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex + 1)); - - QFile thumb(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", sourceIndex + 1)); - thumb.rename(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", targetIndex + 1)); -} - - -void UBPersistenceManager::copyPage(UBDocumentProxy* pDocumentProxy, const int sourceIndex, const int targetIndex) -{ - QFile svg(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex + 1)); - svg.copy(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex + 1)); - - UBSvgSubsetAdaptor::setSceneUuid(pDocumentProxy, targetIndex, QUuid::createUuid()); - - QFile thumb(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", sourceIndex + 1)); - thumb.copy(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", targetIndex + 1)); -} - - -int UBPersistenceManager::sceneCount(const UBDocumentProxy* proxy) -{ - return sceneCountInDir(proxy->persistencePath()); -} - -int UBPersistenceManager::sceneCountInDir(const QString& pPath) -{ - int pageIndex = 0; - bool moreToProcess = true; - - while (moreToProcess) - { - QString fileName = pPath + UBFileSystemUtils::digitFileFormat("/page%1.svg", pageIndex + 1); - - QFile file(fileName); - - if (file.exists()) - { - pageIndex++; - } - else - { - moreToProcess = false; - } - } - - return pageIndex; -} - - -QString UBPersistenceManager::generateUniqueDocumentPath() -{ - QString ubPath = UBSettings::settings()->uniboardDocumentDirectory(); - - QDateTime now = QDateTime::currentDateTime(); - QString dirName = now.toString("yyyy-MM-dd hh-mm-ss.zzz"); - - return ubPath + QString("/Sankore Document %1").arg(dirName); -} - - -void UBPersistenceManager::generatePathIfNeeded(UBDocumentProxy* pDocumentProxy) -{ - if (pDocumentProxy->persistencePath().length() == 0) - { - pDocumentProxy->setPersistencePath(generateUniqueDocumentPath()); - } -} - - -void UBPersistenceManager::addDirectoryContentToDocument(const QString& documentRootFolder, UBDocumentProxy* pDocument) -{ - int sourcePageCount = sceneCountInDir(documentRootFolder); - - int targetPageCount = pDocument->pageCount(); - - for(int sourceIndex = 0 ; sourceIndex < sourcePageCount; sourceIndex++) - { - int targetIndex = targetPageCount + sourceIndex; - - QFile svg(documentRootFolder + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex + 1)); - svg.copy(pDocument->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex + 1)); - - UBSvgSubsetAdaptor::setSceneUuid(pDocument, targetIndex, QUuid::createUuid()); - - QFile thumb(documentRootFolder + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", sourceIndex + 1)); - thumb.copy(pDocument->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", targetIndex + 1)); - } - - foreach(QString dir, mDocumentSubDirectories) - { - qDebug() << "copying " << documentRootFolder << "/" << dir << " to " << pDocument->persistencePath() << "/" + dir; - - UBFileSystemUtils::copyDir(documentRootFolder + "/" + dir, pDocument->persistencePath() + "/" + dir); - } - - pDocument->setPageCount(sceneCount(pDocument)); - -} - - -void UBPersistenceManager::upgradeDocumentIfNeeded(UBDocumentProxy* pDocumentProxy) -{ - int pageCount = pDocumentProxy->pageCount(); - - for(int index = 0 ; index < pageCount; index++) - { - UBSvgSubsetAdaptor::upgradeScene(pDocumentProxy, index); - } - - pDocumentProxy->setMetaData(UBSettings::documentVersion, UBSettings::currentFileVersion); - - UBMetadataDcSubsetAdaptor::persist(pDocumentProxy); -} - - -void UBPersistenceManager::upgradeAllDocumentsIfNeeded() -{ - foreach(QPointer proxy, documentProxies) - { - upgradeDocumentIfNeeded(proxy); - } -} - - - -UBDocumentProxy* UBPersistenceManager::documentByUuid(const QUuid& pUuid) -{ - for(int i = 0 ; i < documentProxies.length(); i++) - { - UBDocumentProxy* proxy = documentProxies.at(i); - - if (proxy && proxy->uuid() == pUuid) - { - return proxy; - } - } - - return 0; - -} - - -bool UBPersistenceManager::isEmpty(UBDocumentProxy* pDocumentProxy) -{ - if(!pDocumentProxy) - return true; - - if (pDocumentProxy->pageCount() > 1) - return false; - - UBGraphicsScene *theSoleScene = UBSvgSubsetAdaptor::loadScene(pDocumentProxy, 0); - - bool empty = false; - - if (theSoleScene) - { - empty = theSoleScene->isEmpty(); - delete theSoleScene; - } - else - { - empty = true; - } - - return empty; -} - - -void UBPersistenceManager::purgeEmptyDocuments() -{ - if(!mHasPurgedDocuments) // hack to workaround the fact that app closing is called twice :-( - { - QList toBeDeleted; - - foreach(UBDocumentProxy* docProxy, mDocumentCreatedDuringSession) - { - if (isEmpty(docProxy)) - { - toBeDeleted << docProxy; - } - } - - foreach(UBDocumentProxy* docProxy, toBeDeleted) - { - deleteDocument(docProxy); - } - - mHasPurgedDocuments = true; - } -} - - -QString UBPersistenceManager::addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid) -{ - QFileInfo fi(path); - - if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) - return ""; - - QString fileName = UBPersistenceManager::videoDirectory + "/" + objectUuid.toString() + "." + fi.suffix(); - - QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; - - if (!QFile::exists(destPath)) - { - QDir dir; - dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::videoDirectory); - - QFile source(path); - - source.copy(destPath); - - } - - return fileName; - -} - - -QString UBPersistenceManager::addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid) -{ - if (!pDocumentProxy || objectUuid.isNull()) - return ""; - - QString urlPath = sourceUrl.path(); - int lastDot = urlPath.lastIndexOf("."); - QString suffix = urlPath.right(urlPath.length() - lastDot - 1); - - QString fileName = UBPersistenceManager::videoDirectory + "/" + objectUuid.toString() + "." + suffix; - QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; - - if (!QFile::exists(destPath)) - { - QDir dir; - dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::videoDirectory); - - QFile newFile(destPath); - - if (newFile.open(QIODevice::WriteOnly)) - { - newFile.write(pPayload); - newFile.flush(); - newFile.close(); - } - } - - return fileName; - -} - - - -QString UBPersistenceManager::addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid) -{ - QFileInfo fi(path); - - if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) - return ""; - - QString fileName = UBPersistenceManager::audioDirectory + "/" + objectUuid.toString() + "." + fi.suffix(); - - QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; - - if (!QFile::exists(destPath)) - { - QDir dir; - dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::audioDirectory); - - QFile source(path); - - source.copy(destPath); - - } - - return fileName; - -} - - -QString UBPersistenceManager::addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid) -{ - if (!pDocumentProxy || objectUuid.isNull()) - return ""; - - QString urlPath = sourceUrl.path(); - int lastDot = urlPath.lastIndexOf("."); - QString suffix = urlPath.right(urlPath.length() - lastDot - 1); - - QString fileName = UBPersistenceManager::audioDirectory + "/" + objectUuid.toString() + "." + suffix; - QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; - - if (!QFile::exists(destPath)) - { - QDir dir; - dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::audioDirectory); - - QFile newFile(destPath); - - if (newFile.open(QIODevice::WriteOnly)) - { - newFile.write(pPayload); - newFile.flush(); - newFile.close(); - } - } - - return fileName; - -} - - -QString UBPersistenceManager::addPdfFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid) -{ - QFileInfo fi(path); - - if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) - return ""; - - QString fileName = UBPersistenceManager::objectDirectory + "/" + objectUuid.toString() + "." + fi.suffix(); - QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; - - if (!QFile::exists(destPath)) - { - QDir dir; - dir.mkpath(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::objectDirectory); - - QFile source(path); - source.copy(destPath); - } - - return fileName; -} -QString UBPersistenceManager::addGraphicsWidgteToDocument(UBDocumentProxy *pDocumentProxy, QString path, QUuid objectUuid) -{ - QFileInfo fi(path); - - if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) - return ""; - - QString widgetRootDir = path; - QString extension = QFileInfo(widgetRootDir).suffix(); - - QString widgetTargetDir = pDocumentProxy->persistencePath() + "/" + widgetDirectory + "/" + objectUuid.toString() + "." + extension; - - if (!QFile::exists(widgetTargetDir)) { - QDir dir; - dir.mkpath(widgetTargetDir); - UBFileSystemUtils::copyDir(widgetRootDir, widgetTargetDir); - } - - if (!QFile::exists(widgetTargetDir)) - widgetTargetDir = QString(); - - return widgetTargetDir; -} - - -void UBPersistenceManager::documentRepositoryChanged(const QString& path) -{ - Q_UNUSED(path); - checkIfDocumentRepositoryExists(); -} - - -void UBPersistenceManager::checkIfDocumentRepositoryExists() -{ - QDir rp(mDocumentRepositoryPath); - - if (!rp.exists()) - { - // we have lost the document repository .. - - QString humanPath = QDir::cleanPath(mDocumentRepositoryPath); - humanPath = QDir::toNativeSeparators(humanPath); - - UBApplication::mainWindow->warning(tr("Document Repository Loss"),tr("Sankore has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well.").arg(humanPath)); - - UBApplication::quit(); - } -} - - -bool UBPersistenceManager::mayHaveVideo(UBDocumentProxy* pDocumentProxy) -{ - QDir videoDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::videoDirectory); - - return videoDir.exists() && videoDir.entryInfoList().length() > 0; -} - -bool UBPersistenceManager::mayHaveAudio(UBDocumentProxy* pDocumentProxy) -{ - QDir audioDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::audioDirectory); - - return audioDir.exists() && audioDir.entryInfoList().length() > 0; -} - -bool UBPersistenceManager::mayHavePDF(UBDocumentProxy* pDocumentProxy) -{ - QDir objectDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::objectDirectory); - - QStringList filters; - filters << "*.pdf"; - - return objectDir.exists() && objectDir.entryInfoList(filters).length() > 0; -} - - -bool UBPersistenceManager::mayHaveSVGImages(UBDocumentProxy* pDocumentProxy) -{ - QDir imageDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::imageDirectory); - - QStringList filters; - filters << "*.svg"; - - return imageDir.exists() && imageDir.entryInfoList(filters).length() > 0; -} - - -bool UBPersistenceManager::mayHaveWidget(UBDocumentProxy* pDocumentProxy) -{ - QDir widgetDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::widgetDirectory); - - return widgetDir.exists() && widgetDir.entryInfoList(QDir::Dirs).length() > 0; -} - -void UBPersistenceManager::persistTeacherBar(UBDocumentProxy* pDocumentProxy, int page, sTeacherBarInfos infos) -{ - if(NULL != pDocumentProxy) - { - QFile f(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", page + 1)); - if(f.exists()) - { - if(f.open(QIODevice::ReadOnly)) - { - QDomDocument domDoc; - if(domDoc.setContent(f.readAll())) - { - f.close(); - if(f.open(QIODevice::WriteOnly)) - { - QDomElement rootElem = domDoc.documentElement(); - QDomNode teacherBarNode = rootElem.namedItem("teacherBar"); - if(teacherBarNode.isNull()) - { - // Create the element - QDomElement teacherElem = domDoc.createElement("teacherBar"); - rootElem.appendChild(teacherElem); - teacherBarNode = teacherElem; - } - - // Set the element values - QDomElement teacherBarElem = teacherBarNode.toElement(); - teacherBarElem.setAttribute("title", infos.title); - - QString qsAct; - for(int i=0; ipersistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", page + 1)); - if(f.exists()) - { - if(f.open(QIODevice::ReadWrite)) - { - QDomDocument domDoc; - if(domDoc.setContent(f.readAll())) - { - QDomElement rootElem = domDoc.documentElement(); - QDomNode teacherBarNode = rootElem.namedItem("teacherBar"); - - infos.title = teacherBarNode.toElement().attributeNode("title").value(); - infos.actions = teacherBarNode.toElement().attributeNode("actions").value().split("@"); - infos.medias = teacherBarNode.toElement().attributeNode("medias").value().split("@"); - infos.urls = teacherBarNode.toElement().attributeNode("links").value().split("@"); - infos.comments = teacherBarNode.toElement().attributeNode("comments").value(); - } - f.close(); - } - } - } - - return infos; -} +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "UBPersistenceManager.h" +#include "gui/UBMainWindow.h" + +#include + +#include "frameworks/UBPlatformUtils.h" +#include "frameworks/UBFileSystemUtils.h" + +#include "core/UBApplication.h" +#include "core/UBSettings.h" +#include "core/UBSetting.h" + +#include "document/UBDocumentProxy.h" + +#include "adaptors/UBExportPDF.h" +#include "adaptors/UBSvgSubsetAdaptor.h" +#include "adaptors/UBThumbnailAdaptor.h" +#include "adaptors/UBMetadataDcSubsetAdaptor.h" + +#include "core/memcheck.h" + +const QString UBPersistenceManager::imageDirectory = "images"; // added to UBPersistenceManager::mAllDirectories +const QString UBPersistenceManager::objectDirectory = "objects"; // added to UBPersistenceManager::mAllDirectories +const QString UBPersistenceManager::widgetDirectory = "widgets"; // added to UBPersistenceManager::mAllDirectories +const QString UBPersistenceManager::videoDirectory = "videos"; // added to UBPersistenceManager::mAllDirectories +const QString UBPersistenceManager::audioDirectory = "audios"; // added to + +UBPersistenceManager * UBPersistenceManager::sSingleton = 0; + +UBPersistenceManager::UBPersistenceManager(QObject *pParent) + : QObject(pParent) + , mHasPurgedDocuments(false) +{ + + mDocumentSubDirectories << imageDirectory; + mDocumentSubDirectories << objectDirectory; + mDocumentSubDirectories << widgetDirectory; + mDocumentSubDirectories << videoDirectory; + mDocumentSubDirectories << audioDirectory; + + documentProxies = allDocumentProxies(); + emit proxyListChanged(); +} + +UBPersistenceManager* UBPersistenceManager::persistenceManager() +{ + if (!sSingleton) + { + sSingleton = new UBPersistenceManager(UBApplication::staticMemoryCleaner); + } + + return sSingleton; +} + +void UBPersistenceManager::destroy() +{ + if (sSingleton) + delete sSingleton; + sSingleton = NULL; +} + +UBPersistenceManager::~UBPersistenceManager() +{ + foreach(QPointer proxyGuard, documentProxies) + { + if (!proxyGuard.isNull()) + delete proxyGuard.data(); + } +} + + +QList > UBPersistenceManager::allDocumentProxies() +{ + mDocumentRepositoryPath = UBSettings::settings()->uniboardDocumentDirectory(); + + QDir rootDir(mDocumentRepositoryPath); + rootDir.mkpath(rootDir.path()); + + + QFileSystemWatcher* watcher = new QFileSystemWatcher(this); + watcher->addPath(mDocumentRepositoryPath); + + connect(watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(documentRepositoryChanged(const QString&))); + + QList > proxies; + + foreach(QString path, rootDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, + QDir::Time | QDir::Reversed)) + { + QString fullPath = rootDir.path() + "/" + path; + + QDir dir(fullPath); + + if (dir.entryList(QDir::Files | QDir::NoDotAndDotDot).size() > 0) + { + UBDocumentProxy* proxy = new UBDocumentProxy(fullPath); // deleted in UBPersistenceManager::destructor + + QMap metadatas = UBMetadataDcSubsetAdaptor::load(fullPath); + + foreach(QString key, metadatas.keys()) + { + proxy->setMetaData(key, metadatas.value(key)); + } + + proxy->setPageCount(sceneCount(proxy)); + + proxies << QPointer(proxy); + + } + } + + return proxies; +} + + +QStringList UBPersistenceManager::allShapes() +{ + QString shapeLibraryPath = UBSettings::settings()->uniboardShapeLibraryDirectory(); + + QDir dir(shapeLibraryPath); + + if (!dir.exists()) + dir.mkpath(shapeLibraryPath); + + QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); + QStringList paths; + + foreach(QString file, files) + { + paths.append(shapeLibraryPath + QString("/") + file); + } + + return paths; +} + +QStringList UBPersistenceManager::allGips() +{ + QString gipLibraryPath = UBSettings::settings()->uniboardGipLibraryDirectory(); + + QDir dir(gipLibraryPath); + + QStringList files = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + QStringList paths; + + foreach(QString file, files) + { + QFileInfo fi(file); + + if (UBSettings::settings()->widgetFileExtensions.contains(fi.suffix())) + paths.append(dir.path() + QString("/") + file); + } + + return paths; +} + +QStringList UBPersistenceManager::allSounds() +{ + QString soundLibraryPath = QDesktopServices::storageLocation(QDesktopServices::MusicLocation); + + QDir dir(soundLibraryPath); + + QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); + QStringList paths; + + foreach(QString file, files) + { + QFileInfo fi(file); + paths.append(dir.path() + QString("/") + file); + } + + return paths; +} + +QStringList UBPersistenceManager::allImages(const QDir& dir) +{ + if (!dir.exists()) + dir.mkpath(dir.path()); + + QStringList files = dir.entryList(QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDir::Name); + QStringList paths; + + foreach(QString file, files) + { + paths.append(dir.path() + QString("/") + file); + } + + return paths; +} + + +QStringList UBPersistenceManager::allVideos(const QDir& dir) +{ + if (!dir.exists()) + dir.mkpath(dir.path()); + + QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name); + QStringList paths; + + foreach(QString file, files) + { + paths.append(dir.path() + QString("/") + file); + } + + return paths; +} + + +QStringList UBPersistenceManager::allWidgets(const QDir& dir) +{ + if (!dir.exists()) + dir.mkpath(dir.path()); + + QStringList files = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + QStringList paths; + + foreach(QString file, files) + { + QFileInfo fi(file); + + if (UBSettings::settings()->widgetFileExtensions.contains(fi.suffix())) + paths.append(dir.path() + QString("/") + file); + } + + return paths; +} + + +UBDocumentProxy* UBPersistenceManager::createDocument(const QString& pGroupName, const QString& pName, bool withEmptyPage) +{ + checkIfDocumentRepositoryExists(); + + UBDocumentProxy *doc = new UBDocumentProxy(); // deleted in UBPersistenceManager::destructor + + if (pGroupName.length() > 0) + { + doc->setMetaData(UBSettings::documentGroupName, pGroupName); + } + + if (pName.length() > 0) + { + doc->setMetaData(UBSettings::documentName, pName); + } + + doc->setMetaData(UBSettings::documentVersion, UBSettings::currentFileVersion); + doc->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); + + if (withEmptyPage) createDocumentSceneAt(doc, 0); + + documentProxies.insert(0, QPointer(doc)); + + emit proxyListChanged(); + + emit documentCreated(doc); + + mDocumentCreatedDuringSession << doc; + + return doc; +} + +UBDocumentProxy* UBPersistenceManager::createDocumentFromDir(const QString& pDocumentDirectory, const QString& pGroupName, const QString& pName, bool withEmptyPage) +{ + checkIfDocumentRepositoryExists(); + + UBDocumentProxy* doc = new UBDocumentProxy(pDocumentDirectory); // deleted in UBPersistenceManager::destructor + + if (pGroupName.length() > 0) + { + doc->setMetaData(UBSettings::documentGroupName, pGroupName); + } + + if (pName.length() > 0) + { + doc->setMetaData(UBSettings::documentName, pName); + } + if (withEmptyPage) createDocumentSceneAt(doc, 0); + + QMap metadatas = UBMetadataDcSubsetAdaptor::load(pDocumentDirectory); + + foreach(QString key, metadatas.keys()) + { + doc->setMetaData(key, metadatas.value(key)); + } + + doc->setUuid(QUuid::createUuid()); + doc->setPageCount(sceneCount(doc)); + + UBMetadataDcSubsetAdaptor::persist(doc); + + for(int i = 0; i < doc->pageCount(); i++) + { + UBSvgSubsetAdaptor::setSceneUuid(doc, i, QUuid::createUuid()); + } + + documentProxies << QPointer(doc); + + emit proxyListChanged(); + + emit documentCreated(doc); + + return doc; +} + + +void UBPersistenceManager::deleteDocument(UBDocumentProxy* pDocumentProxy) +{ + checkIfDocumentRepositoryExists(); + + emit documentWillBeDeleted(pDocumentProxy); + + UBFileSystemUtils::deleteDir(pDocumentProxy->persistencePath()); + + documentProxies.removeAll(QPointer(pDocumentProxy)); + mDocumentCreatedDuringSession.removeAll(pDocumentProxy); + + mSceneCache.removeAllScenes(pDocumentProxy); + + pDocumentProxy->deleteLater(); + + emit proxyListChanged(); + +} + + +UBDocumentProxy* UBPersistenceManager::duplicateDocument(UBDocumentProxy* pDocumentProxy) +{ + checkIfDocumentRepositoryExists(); + + UBDocumentProxy *copy = new UBDocumentProxy(); // deleted in UBPersistenceManager::destructor + + generatePathIfNeeded(copy); + + UBFileSystemUtils::copyDir(pDocumentProxy->persistencePath(), copy->persistencePath()); + + // regenerate scenes UUIDs + for(int i = 0; i < pDocumentProxy->pageCount(); i++) + { + UBSvgSubsetAdaptor::setSceneUuid(pDocumentProxy, i, QUuid::createUuid()); + } + + foreach(QString key, pDocumentProxy->metaDatas().keys()) + { + copy->setMetaData(key, pDocumentProxy->metaDatas().value(key)); + } + + copy->setMetaData(UBSettings::documentName, + pDocumentProxy->metaData(UBSettings::documentName).toString() + " " + tr("(copy)")); + + copy->setUuid(QUuid::createUuid()); + + persistDocumentMetadata(copy); + + copy->setPageCount(sceneCount(copy)); + + documentProxies << QPointer(copy); + + emit proxyListChanged(); + + emit documentCreated(copy); + + return copy; + +} + + +void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QList& indexes) +{ + checkIfDocumentRepositoryExists(); + + int pageCount = UBPersistenceManager::persistenceManager()->sceneCount(proxy); + + QList compactedIndexes; + + foreach(int index, indexes) + { + if (!compactedIndexes.contains(index)) + compactedIndexes.append(index); + } + + if (compactedIndexes.size() == pageCount) + { + deleteDocument(proxy); + return; + } + + if (compactedIndexes.size() == 0) + return; + + foreach(int index, compactedIndexes) + { + emit documentSceneWillBeDeleted(proxy, index); + } + + QString sourceGroupName = proxy->metaData(UBSettings::documentGroupName).toString(); + QString sourceName = proxy->metaData(UBSettings::documentName).toString(); + UBDocumentProxy *trashDocProxy = createDocument(UBSettings::trashedDocumentGroupNamePrefix + sourceGroupName, sourceName, false); + + foreach(int index, compactedIndexes) + { + UBGraphicsScene *scene = loadDocumentScene(proxy, index); + if (scene) + { + //scene is about to move into new document + foreach (QUrl relativeFile, scene->relativeDependencies()) + { + QString source = scene->document()->persistencePath() + "/" + relativeFile.toString(); + QString target = trashDocProxy->persistencePath() + "/" + relativeFile.toString(); + + QFileInfo fi(target); + QDir d = fi.dir(); + + d.mkpath(d.absolutePath()); + QFile::copy(source, target); + } + + insertDocumentSceneAt(trashDocProxy, scene, trashDocProxy->pageCount()); + } + } + + for (int i = 1; i < pageCount; i++) + { + renamePage(trashDocProxy, i , i - 1); + } + + foreach(int index, compactedIndexes) + { + QString svgFileName = proxy->persistencePath() + + UBFileSystemUtils::digitFileFormat("/page%1.svg", index + 1); + + QFile::remove(svgFileName); + + QString thumbFileName = proxy->persistencePath() + + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", index + 1); + + QFile::remove(thumbFileName); + + mSceneCache.removeScene(proxy, index); + + proxy->decPageCount(); + + } + + qSort(compactedIndexes); + + int offset = 1; + + for (int i = compactedIndexes.at(0) + 1; i < pageCount; i++) + { + if(compactedIndexes.contains(i)) + { + offset++; + } + else + { + renamePage(proxy, i , i - offset); + + mSceneCache.moveScene(proxy, i, i - offset); + + } + } + + foreach(int index, compactedIndexes) + { + emit documentSceneDeleted(proxy, index); + } +} + + +void UBPersistenceManager::duplicateDocumentScene(UBDocumentProxy* proxy, int index) +{ + checkIfDocumentRepositoryExists(); + + int pageCount = UBPersistenceManager::persistenceManager()->sceneCount(proxy); + + for (int i = pageCount; i > index + 1; i--) + { + renamePage(proxy, i - 1 , i); + + mSceneCache.moveScene(proxy, i - 1, i); + + } + + copyPage(proxy, index , index + 1); + + proxy->incPageCount(); + + //due to architectural peculiarity we need to save teacher bar info, otherwise we'll see not exactly what we expect + sTeacherBarInfos properInfo = getTeacherBarInfos(proxy, index + 1); + //after the call below + emit documentSceneCreated(proxy, index + 1); + //restoring info + persistTeacherBar(proxy, index + 1, properInfo); +} + + +UBGraphicsScene* UBPersistenceManager::createDocumentSceneAt(UBDocumentProxy* proxy, int index) +{ + int count = sceneCount(proxy); + + for(int i = count - 1; i >= index; i--) + { + renamePage(proxy, i , i + 1); + } + + mSceneCache.shiftUpScenes(proxy, index, count -1); + + UBGraphicsScene *newScene = mSceneCache.createScene(proxy, index); + + newScene->setBackground(UBSettings::settings()->isDarkBackground(), + UBSettings::settings()->UBSettings::isCrossedBackground()); + + persistDocumentScene(proxy, newScene, index); + + proxy->incPageCount(); + + emit documentSceneCreated(proxy, index); + + return newScene; +} + + +void UBPersistenceManager::insertDocumentSceneAt(UBDocumentProxy* proxy, UBGraphicsScene* scene, int index) +{ + scene->setDocument(proxy); + + int count = sceneCount(proxy); + + for(int i = count - 1; i >= index; i--) + { + renamePage(proxy, i , i + 1); + } + + mSceneCache.shiftUpScenes(proxy, index, count -1); + + mSceneCache.insert(proxy, index, scene); + + persistDocumentScene(proxy, scene, index); + + proxy->incPageCount(); + + emit documentSceneCreated(proxy, index); + +} + + +void UBPersistenceManager::moveSceneToIndex(UBDocumentProxy* proxy, int source, int target) +{ + checkIfDocumentRepositoryExists(); + + if (source == target) + return; + + QFile svgTmp(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", source + 1)); + svgTmp.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.tmp", target + 1)); + + QFile thumbTmp(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", source + 1)); + thumbTmp.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.tmp", target + 1)); + + if (source < target) + { + for (int i = source + 1; i <= target; i++) + { + renamePage(proxy, i , i - 1); + } + } + else + { + for (int i = source - 1; i >= target; i--) + { + renamePage(proxy, i , i + 1); + } + } + + QFile svg(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.tmp", target + 1)); + svg.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", target + 1)); + + QFile thumb(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.tmp", target + 1)); + thumb.rename(proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", target + 1)); + + mSceneCache.moveScene(proxy, source, target); + + emit documentSceneMoved(proxy, target); +} + + +UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, int sceneIndex) +{ + if (mSceneCache.contains(proxy, sceneIndex)) + { + //qDebug() << "scene" << sceneIndex << "retrieved from cache ..."; + return mSceneCache.value(proxy, sceneIndex); + } + else + { + UBGraphicsScene* scene = UBSvgSubsetAdaptor::loadScene(proxy, sceneIndex); + + if (scene) + mSceneCache.insert(proxy, sceneIndex, scene); + + return scene; + } +} + + +void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* pScene, const int pSceneIndex) +{ + checkIfDocumentRepositoryExists(); + + pScene->deselectAllItems(); + + generatePathIfNeeded(pDocumentProxy); + + QDir dir(pDocumentProxy->persistencePath()); + dir.mkpath(pDocumentProxy->persistencePath()); + + if (pDocumentProxy->isModified()) + UBMetadataDcSubsetAdaptor::persist(pDocumentProxy); + + if (pScene->isModified()) + { + UBThumbnailAdaptor::persistScene(pDocumentProxy->persistencePath(), pScene, pSceneIndex); + + UBSvgSubsetAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex); + + pScene->setModified(false); + } + + mSceneCache.insert(pDocumentProxy, pSceneIndex, pScene); + + emit documentCommitted(pDocumentProxy); + +} + + +UBDocumentProxy* UBPersistenceManager::persistDocumentMetadata(UBDocumentProxy* pDocumentProxy) +{ + UBMetadataDcSubsetAdaptor::persist(pDocumentProxy); + + emit documentMetadataChanged(pDocumentProxy); + + return pDocumentProxy; +} + + +void UBPersistenceManager::renamePage(UBDocumentProxy* pDocumentProxy, const int sourceIndex, const int targetIndex) +{ + QFile svg(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex + 1)); + svg.rename(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex + 1)); + + QFile thumb(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", sourceIndex + 1)); + thumb.rename(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", targetIndex + 1)); +} + + +void UBPersistenceManager::copyPage(UBDocumentProxy* pDocumentProxy, const int sourceIndex, const int targetIndex) +{ + QFile svg(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex + 1)); + svg.copy(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex + 1)); + + UBSvgSubsetAdaptor::setSceneUuid(pDocumentProxy, targetIndex, QUuid::createUuid()); + + QFile thumb(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", sourceIndex + 1)); + thumb.copy(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", targetIndex + 1)); +} + + +int UBPersistenceManager::sceneCount(const UBDocumentProxy* proxy) +{ + return sceneCountInDir(proxy->persistencePath()); +} + +int UBPersistenceManager::sceneCountInDir(const QString& pPath) +{ + int pageIndex = 0; + bool moreToProcess = true; + + while (moreToProcess) + { + QString fileName = pPath + UBFileSystemUtils::digitFileFormat("/page%1.svg", pageIndex + 1); + + QFile file(fileName); + + if (file.exists()) + { + pageIndex++; + } + else + { + moreToProcess = false; + } + } + + return pageIndex; +} + + +QString UBPersistenceManager::generateUniqueDocumentPath() +{ + QString ubPath = UBSettings::settings()->uniboardDocumentDirectory(); + + QDateTime now = QDateTime::currentDateTime(); + QString dirName = now.toString("yyyy-MM-dd hh-mm-ss.zzz"); + + return ubPath + QString("/Sankore Document %1").arg(dirName); +} + + +void UBPersistenceManager::generatePathIfNeeded(UBDocumentProxy* pDocumentProxy) +{ + if (pDocumentProxy->persistencePath().length() == 0) + { + pDocumentProxy->setPersistencePath(generateUniqueDocumentPath()); + } +} + + +void UBPersistenceManager::addDirectoryContentToDocument(const QString& documentRootFolder, UBDocumentProxy* pDocument) +{ + int sourcePageCount = sceneCountInDir(documentRootFolder); + + int targetPageCount = pDocument->pageCount(); + + for(int sourceIndex = 0 ; sourceIndex < sourcePageCount; sourceIndex++) + { + int targetIndex = targetPageCount + sourceIndex; + + QFile svg(documentRootFolder + UBFileSystemUtils::digitFileFormat("/page%1.svg", sourceIndex + 1)); + svg.copy(pDocument->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", targetIndex + 1)); + + UBSvgSubsetAdaptor::setSceneUuid(pDocument, targetIndex, QUuid::createUuid()); + + QFile thumb(documentRootFolder + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", sourceIndex + 1)); + thumb.copy(pDocument->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", targetIndex + 1)); + } + + foreach(QString dir, mDocumentSubDirectories) + { + qDebug() << "copying " << documentRootFolder << "/" << dir << " to " << pDocument->persistencePath() << "/" + dir; + + UBFileSystemUtils::copyDir(documentRootFolder + "/" + dir, pDocument->persistencePath() + "/" + dir); + } + + pDocument->setPageCount(sceneCount(pDocument)); + +} + + +void UBPersistenceManager::upgradeDocumentIfNeeded(UBDocumentProxy* pDocumentProxy) +{ + int pageCount = pDocumentProxy->pageCount(); + + for(int index = 0 ; index < pageCount; index++) + { + UBSvgSubsetAdaptor::upgradeScene(pDocumentProxy, index); + } + + pDocumentProxy->setMetaData(UBSettings::documentVersion, UBSettings::currentFileVersion); + + UBMetadataDcSubsetAdaptor::persist(pDocumentProxy); +} + + +void UBPersistenceManager::upgradeAllDocumentsIfNeeded() +{ + foreach(QPointer proxy, documentProxies) + { + upgradeDocumentIfNeeded(proxy); + } +} + + + +UBDocumentProxy* UBPersistenceManager::documentByUuid(const QUuid& pUuid) +{ + for(int i = 0 ; i < documentProxies.length(); i++) + { + UBDocumentProxy* proxy = documentProxies.at(i); + + if (proxy && proxy->uuid() == pUuid) + { + return proxy; + } + } + + return 0; + +} + + +bool UBPersistenceManager::isEmpty(UBDocumentProxy* pDocumentProxy) +{ + if(!pDocumentProxy) + return true; + + if (pDocumentProxy->pageCount() > 1) + return false; + + UBGraphicsScene *theSoleScene = UBSvgSubsetAdaptor::loadScene(pDocumentProxy, 0); + + bool empty = false; + + if (theSoleScene) + { + empty = theSoleScene->isEmpty(); + delete theSoleScene; + } + else + { + empty = true; + } + + return empty; +} + + +void UBPersistenceManager::purgeEmptyDocuments() +{ + if(!mHasPurgedDocuments) // hack to workaround the fact that app closing is called twice :-( + { + QList toBeDeleted; + + foreach(UBDocumentProxy* docProxy, mDocumentCreatedDuringSession) + { + if (isEmpty(docProxy)) + { + toBeDeleted << docProxy; + } + } + + foreach(UBDocumentProxy* docProxy, toBeDeleted) + { + deleteDocument(docProxy); + } + + mHasPurgedDocuments = true; + } +} + + +QString UBPersistenceManager::addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid) +{ + QFileInfo fi(path); + + if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) + return ""; + + QString fileName = UBPersistenceManager::videoDirectory + "/" + objectUuid.toString() + "." + fi.suffix(); + + QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; + + if (!QFile::exists(destPath)) + { + QDir dir; + dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::videoDirectory); + + QFile source(path); + + source.copy(destPath); + + } + + return fileName; + +} + + +QString UBPersistenceManager::addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid) +{ + if (!pDocumentProxy || objectUuid.isNull()) + return ""; + + QString urlPath = sourceUrl.path(); + int lastDot = urlPath.lastIndexOf("."); + QString suffix = urlPath.right(urlPath.length() - lastDot - 1); + + QString fileName = UBPersistenceManager::videoDirectory + "/" + objectUuid.toString() + "." + suffix; + QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; + + if (!QFile::exists(destPath)) + { + QDir dir; + dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::videoDirectory); + + QFile newFile(destPath); + + if (newFile.open(QIODevice::WriteOnly)) + { + newFile.write(pPayload); + newFile.flush(); + newFile.close(); + } + } + + return fileName; + +} + + + +QString UBPersistenceManager::addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid) +{ + QFileInfo fi(path); + + if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) + return ""; + + QString fileName = UBPersistenceManager::audioDirectory + "/" + objectUuid.toString() + "." + fi.suffix(); + + QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; + + if (!QFile::exists(destPath)) + { + QDir dir; + dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::audioDirectory); + + QFile source(path); + + source.copy(destPath); + + } + + return fileName; + +} + + +QString UBPersistenceManager::addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid) +{ + if (!pDocumentProxy || objectUuid.isNull()) + return ""; + + QString urlPath = sourceUrl.path(); + int lastDot = urlPath.lastIndexOf("."); + QString suffix = urlPath.right(urlPath.length() - lastDot - 1); + + QString fileName = UBPersistenceManager::audioDirectory + "/" + objectUuid.toString() + "." + suffix; + QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; + + if (!QFile::exists(destPath)) + { + QDir dir; + dir.mkdir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::audioDirectory); + + QFile newFile(destPath); + + if (newFile.open(QIODevice::WriteOnly)) + { + newFile.write(pPayload); + newFile.flush(); + newFile.close(); + } + } + + return fileName; + +} + + +QString UBPersistenceManager::addPdfFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid) +{ + QFileInfo fi(path); + + if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) + return ""; + + QString fileName = UBPersistenceManager::objectDirectory + "/" + objectUuid.toString() + "." + fi.suffix(); + QString destPath = pDocumentProxy->persistencePath() + "/" + fileName; + + if (!QFile::exists(destPath)) + { + QDir dir; + dir.mkpath(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::objectDirectory); + + QFile source(path); + source.copy(destPath); + } + + return fileName; +} +QString UBPersistenceManager::addGraphicsWidgteToDocument(UBDocumentProxy *pDocumentProxy, QString path, QUuid objectUuid) +{ + QFileInfo fi(path); + + if (!fi.exists() || !pDocumentProxy || objectUuid.isNull()) + return ""; + + QString widgetRootDir = path; + QString extension = QFileInfo(widgetRootDir).suffix(); + + QString widgetTargetDir = pDocumentProxy->persistencePath() + "/" + widgetDirectory + "/" + objectUuid.toString() + "." + extension; + + if (!QFile::exists(widgetTargetDir)) { + QDir dir; + dir.mkpath(widgetTargetDir); + UBFileSystemUtils::copyDir(widgetRootDir, widgetTargetDir); + } + + if (!QFile::exists(widgetTargetDir)) + widgetTargetDir = QString(); + + return widgetTargetDir; +} + + +void UBPersistenceManager::documentRepositoryChanged(const QString& path) +{ + Q_UNUSED(path); + checkIfDocumentRepositoryExists(); +} + + +void UBPersistenceManager::checkIfDocumentRepositoryExists() +{ + QDir rp(mDocumentRepositoryPath); + + if (!rp.exists()) + { + // we have lost the document repository .. + + QString humanPath = QDir::cleanPath(mDocumentRepositoryPath); + humanPath = QDir::toNativeSeparators(humanPath); + + UBApplication::mainWindow->warning(tr("Document Repository Loss"),tr("Sankore has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well.").arg(humanPath)); + + UBApplication::quit(); + } +} + + +bool UBPersistenceManager::mayHaveVideo(UBDocumentProxy* pDocumentProxy) +{ + QDir videoDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::videoDirectory); + + return videoDir.exists() && videoDir.entryInfoList().length() > 0; +} + +bool UBPersistenceManager::mayHaveAudio(UBDocumentProxy* pDocumentProxy) +{ + QDir audioDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::audioDirectory); + + return audioDir.exists() && audioDir.entryInfoList().length() > 0; +} + +bool UBPersistenceManager::mayHavePDF(UBDocumentProxy* pDocumentProxy) +{ + QDir objectDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::objectDirectory); + + QStringList filters; + filters << "*.pdf"; + + return objectDir.exists() && objectDir.entryInfoList(filters).length() > 0; +} + + +bool UBPersistenceManager::mayHaveSVGImages(UBDocumentProxy* pDocumentProxy) +{ + QDir imageDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::imageDirectory); + + QStringList filters; + filters << "*.svg"; + + return imageDir.exists() && imageDir.entryInfoList(filters).length() > 0; +} + + +bool UBPersistenceManager::mayHaveWidget(UBDocumentProxy* pDocumentProxy) +{ + QDir widgetDir(pDocumentProxy->persistencePath() + "/" + UBPersistenceManager::widgetDirectory); + + return widgetDir.exists() && widgetDir.entryInfoList(QDir::Dirs).length() > 0; +} + +void UBPersistenceManager::persistTeacherBar(UBDocumentProxy* pDocumentProxy, int page, sTeacherBarInfos infos) +{ + if(NULL != pDocumentProxy) + { + QFile f(pDocumentProxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", page + 1)); + if(f.exists()) + { + if(f.open(QIODevice::ReadOnly)) + { + QDomDocument domDoc; + if(domDoc.setContent(f.readAll())) + { + f.close(); + if(f.open(QIODevice::WriteOnly)) + { + QDomElement rootElem = domDoc.documentElement(); + QDomNode teacherBarNode = rootElem.namedItem("teacherBar"); + if(teacherBarNode.isNull()) + { + // Create the element + QDomElement teacherElem = domDoc.createElement("teacherBar"); + rootElem.appendChild(teacherElem); + teacherBarNode = teacherElem; + } + + // Set the element values + QDomElement teacherBarElem = teacherBarNode.toElement(); + teacherBarElem.setAttribute("title", infos.title); + + QString qsAct; + for(int i=0; ipersistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.svg", page + 1)); + if(f.exists()) + { + if(f.open(QIODevice::ReadWrite)) + { + QDomDocument domDoc; + if(domDoc.setContent(f.readAll())) + { + QDomElement rootElem = domDoc.documentElement(); + QDomNode teacherBarNode = rootElem.namedItem("teacherBar"); + + infos.title = teacherBarNode.toElement().attributeNode("title").value(); + infos.actions = teacherBarNode.toElement().attributeNode("actions").value().split("@"); + infos.medias = teacherBarNode.toElement().attributeNode("medias").value().split("@"); + infos.urls = teacherBarNode.toElement().attributeNode("links").value().split("@"); + infos.comments = teacherBarNode.toElement().attributeNode("comments").value(); + } + f.close(); + } + } + } + + return infos; +} diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h index 21c29308..63943150 100644 --- a/src/core/UBPersistenceManager.h +++ b/src/core/UBPersistenceManager.h @@ -1,175 +1,175 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef UBPERSISTENCEMANAGER_H_ -#define UBPERSISTENCEMANAGER_H_ - -#include - -#include "UBSceneCache.h" - -struct sTeacherBarInfos -{ - QString title; - QStringList actions; - QStringList medias; - QStringList urls; - QString comments; -}; - -class UBDocument; -class UBDocumentProxy; -class UBGraphicsScene; - -class UBPersistenceManager : public QObject -{ - Q_OBJECT - - private: - UBPersistenceManager(QObject *pParent = 0); - static UBPersistenceManager* sSingleton; - - public: - - virtual ~UBPersistenceManager(); - - static const QString imageDirectory; - static const QString objectDirectory; - static const QString videoDirectory; - static const QString audioDirectory; - static const QString widgetDirectory; - - static UBPersistenceManager* persistenceManager(); - static void destroy(); - - virtual UBDocumentProxy* createDocument(const QString& pGroupName = "", const QString& pName = "", bool withEmptyPage = true); - virtual UBDocumentProxy* createDocumentFromDir(const QString& pDocumentDirectory); - - virtual UBDocumentProxy* persistDocumentMetadata(UBDocumentProxy* pDocumentProxy); - - virtual UBDocumentProxy* duplicateDocument(UBDocumentProxy* pDocumentProxy); - - virtual void deleteDocument(UBDocumentProxy* pDocumentProxy); - - virtual void deleteDocumentScenes(UBDocumentProxy* pDocumentProxy, const QList& indexes); - - virtual void duplicateDocumentScene(UBDocumentProxy* pDocumentProxy, int index); - - virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy, - UBGraphicsScene* pScene, const int pSceneIndex); - virtual void persistTeacherBar(UBDocumentProxy* pDocumentProxy, int page, sTeacherBarInfos infos); - - sTeacherBarInfos getTeacherBarInfos(UBDocumentProxy* pDocumentProxy, int page); - - virtual UBGraphicsScene* createDocumentSceneAt(UBDocumentProxy* pDocumentProxy, int index); - - virtual void insertDocumentSceneAt(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* scene, int index); - - virtual void moveSceneToIndex(UBDocumentProxy* pDocumentProxy, int source, int target); - - virtual UBGraphicsScene* loadDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex); - UBGraphicsScene *getDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex) {return mSceneCache.value(pDocumentProxy, sceneIndex);} - - QList > documentProxies; - - virtual QStringList allShapes(); - virtual QStringList allGips(); - virtual QStringList allSounds(); - virtual QStringList allImages(const QDir& dir); - virtual QStringList allVideos(const QDir& dir); - virtual QStringList allWidgets(const QDir& dir); - - virtual QString generateUniqueDocumentPath(); - - virtual void addDirectoryContentToDocument(const QString& documentRootFolder, UBDocumentProxy* pDocument); - - virtual void upgradeDocumentIfNeeded(UBDocumentProxy* pDocumentProxy); - - virtual void upgradeAllDocumentsIfNeeded(); - - virtual UBDocumentProxy* documentByUuid(const QUuid& pUuid); - - QStringList documentSubDirectories() - { - return mDocumentSubDirectories; - } - - virtual bool isEmpty(UBDocumentProxy* pDocumentProxy); - virtual void purgeEmptyDocuments(); - - virtual QString addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid); - virtual QString addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid); - virtual QString addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid); - virtual QString addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid); - virtual QString addPdfFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid); - virtual QString addGraphicsWidgteToDocument(UBDocumentProxy *mDocumentProxy, QString path, QUuid objectUuid); - - bool mayHaveVideo(UBDocumentProxy* pDocumentProxy); - bool mayHaveAudio(UBDocumentProxy* pDocumentProxy); - bool mayHavePDF(UBDocumentProxy* pDocumentProxy); - bool mayHaveSVGImages(UBDocumentProxy* pDocumentProxy); - bool mayHaveWidget(UBDocumentProxy* pDocumentProxy); - - signals: - - void proxyListChanged(); - - void documentCreated(UBDocumentProxy* pDocumentProxy); - void documentMetadataChanged(UBDocumentProxy* pDocumentProxy); - void documentCommitted(UBDocumentProxy* pDocumentProxy); - void documentWillBeDeleted(UBDocumentProxy* pDocumentProxy); - - void documentSceneCreated(UBDocumentProxy* pDocumentProxy, int pIndex); - void documentSceneMoved(UBDocumentProxy* pDocumentProxy, int pIndex); - void documentSceneWillBeDeleted(UBDocumentProxy* pDocumentProxy, int pIndex); - void documentSceneDeleted(UBDocumentProxy* pDocumentProxy, int pDeletedIndex); - - private: - - int sceneCount(const UBDocumentProxy* pDocumentProxy); - - int sceneCountInDir(const QString& pPath); - - QList > allDocumentProxies(); - - void renamePage(UBDocumentProxy* pDocumentProxy, - const int sourceIndex, const int targetIndex); - - void copyPage(UBDocumentProxy* pDocumentProxy, - const int sourceIndex, const int targetIndex); - - void generatePathIfNeeded(UBDocumentProxy* pDocumentProxy); - - void checkIfDocumentRepositoryExists(); - - UBSceneCache mSceneCache; - - QStringList mDocumentSubDirectories; - - QMutex mDeletedListMutex; - - bool mHasPurgedDocuments; - - QList mDocumentCreatedDuringSession; - - QString mDocumentRepositoryPath; - - private slots: - void documentRepositoryChanged(const QString& path); - -}; - - -#endif /* UBPERSISTENCEMANAGER_H_ */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef UBPERSISTENCEMANAGER_H_ +#define UBPERSISTENCEMANAGER_H_ + +#include + +#include "UBSceneCache.h" + +struct sTeacherBarInfos +{ + QString title; + QStringList actions; + QStringList medias; + QStringList urls; + QString comments; +}; + +class UBDocument; +class UBDocumentProxy; +class UBGraphicsScene; + +class UBPersistenceManager : public QObject +{ + Q_OBJECT + + private: + UBPersistenceManager(QObject *pParent = 0); + static UBPersistenceManager* sSingleton; + + public: + + virtual ~UBPersistenceManager(); + + static const QString imageDirectory; + static const QString objectDirectory; + static const QString videoDirectory; + static const QString audioDirectory; + static const QString widgetDirectory; + + static UBPersistenceManager* persistenceManager(); + static void destroy(); + + virtual UBDocumentProxy* createDocument(const QString& pGroupName = "", const QString& pName = "", bool withEmptyPage = true); + virtual UBDocumentProxy* createDocumentFromDir(const QString& pDocumentDirectory, const QString& pGroupName = "", const QString& pName = "", bool withEmptyPage = false); + + virtual UBDocumentProxy* persistDocumentMetadata(UBDocumentProxy* pDocumentProxy); + + virtual UBDocumentProxy* duplicateDocument(UBDocumentProxy* pDocumentProxy); + + virtual void deleteDocument(UBDocumentProxy* pDocumentProxy); + + virtual void deleteDocumentScenes(UBDocumentProxy* pDocumentProxy, const QList& indexes); + + virtual void duplicateDocumentScene(UBDocumentProxy* pDocumentProxy, int index); + + virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy, + UBGraphicsScene* pScene, const int pSceneIndex); + virtual void persistTeacherBar(UBDocumentProxy* pDocumentProxy, int page, sTeacherBarInfos infos); + + sTeacherBarInfos getTeacherBarInfos(UBDocumentProxy* pDocumentProxy, int page); + + virtual UBGraphicsScene* createDocumentSceneAt(UBDocumentProxy* pDocumentProxy, int index); + + virtual void insertDocumentSceneAt(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* scene, int index); + + virtual void moveSceneToIndex(UBDocumentProxy* pDocumentProxy, int source, int target); + + virtual UBGraphicsScene* loadDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex); + UBGraphicsScene *getDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex) {return mSceneCache.value(pDocumentProxy, sceneIndex);} + + QList > documentProxies; + + virtual QStringList allShapes(); + virtual QStringList allGips(); + virtual QStringList allSounds(); + virtual QStringList allImages(const QDir& dir); + virtual QStringList allVideos(const QDir& dir); + virtual QStringList allWidgets(const QDir& dir); + + virtual QString generateUniqueDocumentPath(); + + virtual void addDirectoryContentToDocument(const QString& documentRootFolder, UBDocumentProxy* pDocument); + + virtual void upgradeDocumentIfNeeded(UBDocumentProxy* pDocumentProxy); + + virtual void upgradeAllDocumentsIfNeeded(); + + virtual UBDocumentProxy* documentByUuid(const QUuid& pUuid); + + QStringList documentSubDirectories() + { + return mDocumentSubDirectories; + } + + virtual bool isEmpty(UBDocumentProxy* pDocumentProxy); + virtual void purgeEmptyDocuments(); + + virtual QString addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid); + virtual QString addVideoFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid); + virtual QString addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid); + virtual QString addAudioFileToDocument(UBDocumentProxy* pDocumentProxy, QUrl sourceUrl, QByteArray pPayload, QUuid objectUuid); + virtual QString addPdfFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, QUuid objectUuid); + virtual QString addGraphicsWidgteToDocument(UBDocumentProxy *mDocumentProxy, QString path, QUuid objectUuid); + + bool mayHaveVideo(UBDocumentProxy* pDocumentProxy); + bool mayHaveAudio(UBDocumentProxy* pDocumentProxy); + bool mayHavePDF(UBDocumentProxy* pDocumentProxy); + bool mayHaveSVGImages(UBDocumentProxy* pDocumentProxy); + bool mayHaveWidget(UBDocumentProxy* pDocumentProxy); + + signals: + + void proxyListChanged(); + + void documentCreated(UBDocumentProxy* pDocumentProxy); + void documentMetadataChanged(UBDocumentProxy* pDocumentProxy); + void documentCommitted(UBDocumentProxy* pDocumentProxy); + void documentWillBeDeleted(UBDocumentProxy* pDocumentProxy); + + void documentSceneCreated(UBDocumentProxy* pDocumentProxy, int pIndex); + void documentSceneMoved(UBDocumentProxy* pDocumentProxy, int pIndex); + void documentSceneWillBeDeleted(UBDocumentProxy* pDocumentProxy, int pIndex); + void documentSceneDeleted(UBDocumentProxy* pDocumentProxy, int pDeletedIndex); + + private: + + int sceneCount(const UBDocumentProxy* pDocumentProxy); + + int sceneCountInDir(const QString& pPath); + + QList > allDocumentProxies(); + + void renamePage(UBDocumentProxy* pDocumentProxy, + const int sourceIndex, const int targetIndex); + + void copyPage(UBDocumentProxy* pDocumentProxy, + const int sourceIndex, const int targetIndex); + + void generatePathIfNeeded(UBDocumentProxy* pDocumentProxy); + + void checkIfDocumentRepositoryExists(); + + UBSceneCache mSceneCache; + + QStringList mDocumentSubDirectories; + + QMutex mDeletedListMutex; + + bool mHasPurgedDocuments; + + QList mDocumentCreatedDuringSession; + + QString mDocumentRepositoryPath; + + private slots: + void documentRepositoryChanged(const QString& path); + +}; + + +#endif /* UBPERSISTENCEMANAGER_H_ */