diff --git a/src/adaptors/UBExportDocumentSetAdaptor.cpp b/src/adaptors/UBExportDocumentSetAdaptor.cpp index 752b5ea38..847e84728 100644 --- a/src/adaptors/UBExportDocumentSetAdaptor.cpp +++ b/src/adaptors/UBExportDocumentSetAdaptor.cpp @@ -38,7 +38,6 @@ #include "globals/UBGlobals.h" #include "core/UBPersistenceManager.h" -#include "core/UBForeignObjectsHandler.h" #ifdef Q_OS_OSX #include @@ -164,16 +163,9 @@ bool UBExportDocumentSetAdaptor::addDocumentToZip(const QModelIndex &pIndex, UBD } std::shared_ptrpDocumentProxy = model->proxyForIndex(parentIndex); - if (pDocumentProxy) { - -// Q_ASSERT(QFileInfo(pDocumentProxy->persistencePath()).exists()); -// UBForeighnObjectsHandler cleaner; -// cleaner.cure(pDocumentProxy->persistencePath()); - - //UniboardSankoreTransition document; + if (pDocumentProxy) + { QString documentPath(pDocumentProxy->persistencePath()); - //document.checkDocumentDirectory(documentPath); - QDir documentDir = QDir(pDocumentProxy->persistencePath()); QuaZipFile zipFile(&zip); UBFileSystemUtils::compressDirInZip(documentDir, QFileInfo(documentPath).fileName() + "/", &zipFile, false); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4ac038907..6bbca8173 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -13,8 +13,6 @@ target_sources(${PROJECT_NAME} PRIVATE UBDownloadManager.h UBDownloadThread.cpp UBDownloadThread.h - UBForeignObjectsHandler.cpp - UBForeignObjectsHandler.h UBIdleTimer.cpp UBIdleTimer.h UBMimeData.cpp diff --git a/src/core/UBForeignObjectsHandler.cpp b/src/core/UBForeignObjectsHandler.cpp deleted file mode 100644 index 1ad3ee982..000000000 --- a/src/core/UBForeignObjectsHandler.cpp +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (C) 2015-2022 Département de l'Instruction Publique (DIP-SEM) - * - * Copyright (C) 2013 Open Education Foundation - * - * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour - * l'Education Numérique en Afrique (GIP ENA) - * - * This file is part of OpenBoard. - * - * OpenBoard 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, version 3 of the License, - * with a specific linking exception for the OpenSSL project's - * "OpenSSL" library (or with modified versions of it that use the - * same license as the "OpenSSL" library). - * - * OpenBoard 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 OpenBoard. If not, see . - */ - -#include "UBForeignObjectsHandler.h" - -#include -#include -#include "UBSettings.h" - -const QString tVideo = "video"; -const QString tAudio = "audio"; -const QString tImage = "image"; -const QString tForeignObject = "foreignObject"; -const QString tTeacherGuide = "teacherGuide"; -const QString tMedia = "media"; -const QString tGroups = "groups"; - -const QString aHref = "xlink:href"; -const QString aType = "ub:type"; -const QString aReqExt = "requiredExtensions"; -const QString aSrc = "ub:src"; -const QString aMediaType = "mediaType"; -const QString aRelativePath = "relativePath"; -const QString aActionMedia = "ub:actionFirstParameter"; - -const QString vText = "text"; -const QString vReqExt = "http://ns.adobe.com/pdf/1.3/"; - -const QString wgtSuff = ".wgt"; -const QString thumbSuff = ".png"; - -const QString scanDirs = "audios,images,videos,teacherGuideObjects,widgets"; -const QStringList trashFilter = QStringList() << "*.swf"; - - -static QString strIdFrom(const QString &filePath) -{ - if ((filePath).isEmpty()) { - return QString(); - } - - static const QRegularExpression rx("\\{.(?!.*\\{).*\\}"); - QRegularExpressionMatch match = rx.match(filePath); - if (!match.hasMatch()) { - return QString(); - } - - return match.captured(); -} - -static bool rm_r(const QString &rmPath) -{ - QFileInfo fi(rmPath); - if (!fi.exists()) { - qDebug() << rmPath << "does not exist"; - return false; - } else if (fi.isFile()) { - if (!QFile::remove(rmPath)) { - qDebug() << "can't remove file" << rmPath; - return false; - } - return true; - } else if (fi.isDir()) { - QFileInfoList fList = QDir(rmPath).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot); - foreach (QFileInfo sub, fList) { - rm_r(sub.absoluteFilePath()); - } - if (!QDir().rmdir(rmPath)) { - qDebug() << "can't remove dir" << rmPath; - return false; - } - return true; - } - return false; -} - -static bool cp_rf(const QString &what, const QString &where) -{ - QFileInfo whatFi(what); - QFileInfo whereFi = QFileInfo(where); - - if (!whatFi.exists()) { - qDebug() << what << "does not exist" << Q_FUNC_INFO; - return false; - } else if (whatFi.isFile()) { - QString whereDir = where.section("/", 0, -2, QString::SectionSkipEmpty | QString::SectionIncludeLeadingSep); - QString newFilePath = where; - if (!whereFi.exists()) { - QDir().mkpath(whereDir); - } else if (whereFi.isDir()) { - newFilePath = whereDir + "/" + whatFi.fileName(); - } - if (QFile::exists(newFilePath)) { - QFile::remove(newFilePath); - } - if (!QFile::copy(what, newFilePath)) { - qDebug() << "can't copy" << what << "to" << where << Q_FUNC_INFO; - return false; - } - return true; - } else if (whatFi.isDir()) { - - if (whereFi.isFile() && whereFi.fileName().toLower() == whatFi.fileName().toLower()) { - qDebug() << "can't copy dir" << what << "to file" << where << Q_FUNC_INFO; - return false; - } else if (whereFi.isDir()) { - rm_r(where); - } - - QDir().mkpath(where); - - QFileInfoList fList = QDir(what).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot); - foreach (QFileInfo sub, fList) { - if (!cp_rf(sub.absoluteFilePath(), where + "/" + sub.fileName())) - return false; - } - return true; - } - return true; -} - -static QString thumbFileNameFrom(const QString &filePath) -{ - if (filePath.isEmpty()) { - return QString(); - } - - static const QRegularExpression braces("[\\{\\}]"); - QString thumbPath = filePath; - thumbPath.replace(braces, "").replace(wgtSuff, thumbSuff); - - return thumbPath; -} - - -QString svgPageName(int pageIndex) -{ - return QString("page%1.svg").arg(pageIndex, 3, 10, QLatin1Char('0')); -} - -static QDomDocument createDomFromSvg(const QString &svgUrl) -{ - Q_ASSERT(QFile::exists(svgUrl)); - QString mFoldersXmlStorageName = svgUrl; - - if (QFileInfo(mFoldersXmlStorageName).exists()) { - QDomDocument xmlDom; - QFile inFile(mFoldersXmlStorageName); - if (inFile.open(QIODevice::ReadOnly)) { - QString domString(inFile.readAll()); - - int errorLine = 0; int errorColumn = 0; - QString errorStr; - - if (xmlDom.setContent(domString, &errorStr, &errorLine, &errorColumn)) { - return xmlDom; - } else { - qDebug() << "Error reading content of " << mFoldersXmlStorageName << '\n' - << "Error:" << inFile.errorString() - << "Line:" << errorLine - << "Column:" << errorColumn; - } - inFile.close(); - } else { - qDebug() << "Error reading" << mFoldersXmlStorageName << '\n' - << "Error:" << inFile.errorString(); - } - } - - return QDomDocument(); -} - -class Cleaner -{ -public: - void cure(const QUrl &dir) - { - mCurrentDir = dir.toLocalFile(); - cleanTrash(); - - // Gathering information from svg files - QFileInfoList svgInfos = QDir(mCurrentDir).entryInfoList(QStringList() << "*.svg", QDir::NoDotAndDotDot | QDir::Files); - foreach (QFileInfo svgInfo, svgInfos) { - cureIdsFromSvgDom(createDomFromSvg(svgInfo.absoluteFilePath())); - } - - fitIdsFromFileSystem(); - QVector deleteCandidates; - findRedundandElements(deleteCandidates); - - foreach (QString key, deleteCandidates) { - QString delPath = mPresentIdsMap.value(key); - if (delPath.isNull()) { - continue; - } else if (delPath.endsWith(wgtSuff)) { //remove corresponding thumb - QString thumbPath = thumbFileNameFrom(delPath); - - //N/C - NNE - 20140417 - if (QFile::exists(thumbPath)) { - rm_r(thumbPath); - } - } - rm_r(delPath); - // Clear parent dir if empty - QDir dir(delPath); - dir.cdUp(); - if (dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) { - dir.rmdir(dir.absolutePath()); - } - } - - qDebug() << "Ok on cure"; - } - -private: - void cleanTrash() - { - QFileInfoList ifs = QDir(mCurrentDir).entryInfoList(trashFilter, QDir::NoDotAndDotDot | QDir::Files); - foreach (QFileInfo ifo, ifs) { - rm_r(ifo.absoluteFilePath()); - } - } - - void cureIdsFromSvgDom(const QDomDocument &dom) - { - Q_ASSERT(!dom.isNull()); - - QDomElement nextElement = dom.documentElement().firstChildElement(); - while (!nextElement.isNull()) { - QString nextTag = nextElement.tagName(); - qDebug() << "Tag name of the next parsed element is" << nextTag; - if (nextTag == tGroups) - { - nextElement = nextElement.firstChildElement("group"); - } - - invokeFromText(nextTag, nextElement); - nextElement = nextElement.nextSiblingElement(); - } - } - - void fitIdsFromFileSystem() - { - QString absPrefix = mCurrentDir + "/"; - QStringList dirsList = scanDirs.split(",", UB::SplitBehavior::SkipEmptyParts); - foreach (QString dirName, dirsList) { - QString absPath = absPrefix + dirName; - if (!QFile::exists(absPath)) { - continue; - } - fitIdsFromDir(absPath); - } - - } - - void fitIdsFromDir(const QString &scanDir) - { - QFileInfoList fileList = QDir(scanDir).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); - foreach (QFileInfo nInfo, fileList) { - QString uid = strIdFrom(nInfo.fileName()); - if (uid.isNull()) { - continue; - } - mPresentIdsMap.insert(uid, nInfo.absoluteFilePath()); - } - } - - void findRedundandElements(QVector &v) - { - // Taking information from the physical file system - QStringList domIds = mDomIdsMap.keys(); - QStringList presentIds = mPresentIdsMap.keys(); - v.resize(qMax(domIds.count(), presentIds.count())); - QVector::iterator it_diff; - - it_diff=std::set_symmetric_difference(domIds.begin(), domIds.end() - , presentIds.begin(), presentIds.end() - , v.begin()); - v.resize(it_diff - v.begin()); - } - - void invokeFromText(const QString &what, const QDomElement &element) - { - if (what == tVideo - || what == tAudio - || what == tImage) { - mediaToContainer(element); - } else if (what == tForeignObject) { - foreingObjectToContainer(element); - - //N/C - NNE - 20140317 - cleanObjectFolder(element); - - //N/C - NNE - 20140520 - //foreign object may referer resource which are not present in the svg - addResourceIdToSvg(element); - } else if (what == tTeacherGuide) { - teacherGuideToContainer(element); - } - - pullActionFromElement(element); - } - - // N/C - NNE - 20140317 : When export, reduce the size of the ubz file - void cleanObjectFolder(const QDomElement &element) - { - //QDomElement preference = element.firstChildElement("ub:preference"); - - //N/C - NNE - 20141021 - QDomNodeList childrenNode = element.elementsByTagName("ub:preference"); - - QVector objectsIdUsed; - - for(int i = 0; i < childrenNode.size(); i++){ - QDomElement preference = childrenNode.at(i).toElement(); - - if(!preference.isNull()){ - QString value = preference.attribute("value"); - - int findPos = value.indexOf("objects/"); - int endPos; - - //find all objects used - while(findPos != -1){ - endPos = value.indexOf("\"", findPos); - objectsIdUsed << value.mid(findPos, endPos - findPos); - findPos = value.indexOf("objects/", endPos); - } - } - } - //N/C - NNE - 20141021 : END - - - QString path = element.attribute(aSrc); - QString objectsFolderPath = mCurrentDir + "/" + path + "/objects/"; - - QDir dir(objectsFolderPath); - dir.setFilter(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot); - - //then check all files in the objects directory - //delete the file not used (not in te objectIdUsed variable) - QFileInfoList list = dir.entryInfoList(); - for (int i = 0; i < list.size(); i++) { - QFileInfo fileInfo = list.at(i); - - if(!objectsIdUsed.contains("objects/"+fileInfo.fileName())){ - QFile(fileInfo.filePath()).remove(); - } - - } - } - // N/C - NNE - 20140317 : END - - //N/C - NNE - 20140520 - void addResourceIdToSvg(const QDomElement& element) - { - QDomElement textContent = element.firstChildElement("itemTextContent"); - - QString value = textContent.text(); - - int findPos = value.indexOf("images/"); - int endPos; - - //find all objects used - while(findPos != -1){ - endPos = value.indexOf("\"", findPos); - - QString path = value.mid(findPos, endPos - findPos); - - QString uuid = path.split("/").at(1).split(".").at(0); - - mDomIdsMap.insert(uuid, path); - - findPos = value.indexOf("images/", endPos); - } - } - //N/C - NNE - 20140520 : END - - void pullActionFromElement(const QDomElement &element) - { - if (!element.hasAttribute(aActionMedia)) { - return; - } - - QString path = element.attribute(aActionMedia); - if (path.isNull()) { - return; - } - - QString uid = strIdFrom(path); - if (uid.isNull()) { - return; - } - - mDomIdsMap.insert(uid, path); - } - - void teacherGuideToContainer(const QDomElement &element) - { - QDomElement nMediaElement = element.firstChildElement(tMedia); - while (!nMediaElement.isNull()) { - - QString path = nMediaElement.attribute(aRelativePath); - if (path.isNull()) { - continue; - } - - QString uid = strIdFrom(path); - if (uid.isNull()) { - return; - } - mDomIdsMap.insert(uid, path); - - nMediaElement = nMediaElement.nextSiblingElement(tMedia); - } - } - - void mediaToContainer(const QDomElement &element) - { - QString path = element.attribute(aHref); - if (path.isNull()) { - return; - } - QString uid = strIdFrom(path); - if (uid.isNull()) { - return; - } - mDomIdsMap.insert(uid, path); - } - - void foreingObjectToContainer(const QDomElement &element) - { - QString type = element.attribute(aType); - if (type == vText) { // We don't have to care of the text object - return; - } - - QString path = element.attribute(aSrc); - if (path.isNull()) { - return; - } - - QString uid = strIdFrom(path); - if (uid.isNull()) { - return; - } - - mDomIdsMap.insert(uid, path); - } - -private: - QString mCurrentDir; - QDomDocument mSvgData; - QMap mDomIdsMap; - QMap mPresentIdsMap; -}; - -class PageCopier -{ -public: - void copyPage (const QUrl &fromDir, int fromIndex, const QUrl &toDir, int toIndex) - { - mFromDir = fromDir.toLocalFile(); - mToDir = toDir.toLocalFile(); - mFromIndex = fromIndex; - mToIndex = toIndex; - - QString svgFrom = mFromDir + "/" + svgPageName(fromIndex); - QString svgTo = toDir.toLocalFile() + "/" + svgPageName(toIndex); - QDomDocument dd = createDomFromSvg(svgFrom); - QFile fl(svgTo); - if (!fl.open(QIODevice::WriteOnly)) { - qDebug() << Q_FUNC_INFO << "can't open" << fl.fileName() << "for writing"; - return; - } - cureIdsFromSvgDom(dd); - - QTextStream str(&fl); - dd.save(str, 0); - fl.close(); - qDebug() << Q_FUNC_INFO; - } - -private: - void cureIdsFromSvgDom(const QDomDocument &dom) - { - Q_ASSERT(!dom.isNull()); - - QDomElement nextElement = dom.documentElement().firstChildElement(); - while (!nextElement.isNull( )) { - qDebug() << "Tag name of the next parsed element is" << nextElement.tagName(); - QString nextTag = nextElement.tagName(); - cureFromText(nextTag, nextElement); - nextElement = nextElement.nextSiblingElement(); - } - } - - void cureFromText(const QString &tagName, QDomElement element) - { - if (tagName == tVideo - || tagName == tAudio - || tagName == tImage) { - QString newRelative = cureNCopy(element.attribute(aHref)); - element.setAttribute(aHref, newRelative); - if (element.hasAttribute(aActionMedia)) { - QString newActionPath = cureNCopy(element.attribute(aActionMedia)); - element.setAttribute(aActionMedia, newActionPath); - } - } else if (tagName == tForeignObject) { - //Pdf object is a special case. Detect if it ends with #reference - QString reqExt = element.attribute(aReqExt); - if (reqExt == vReqExt) { //pdf reference - QString ref = element.attribute(aHref); - int i = ref.indexOf("#page"); - QString dest = ref.replace(i, ref.length()-i, ""); - if (!QFileInfo::exists(dest)) - cureNCopy(dest, false); - if (ref.isEmpty()) { - return; - } - static const QRegularExpression pdfReference("^(.*pdf\\#page\\=).*$"); - ref.replace(pdfReference, QString("\\1%1").arg(mToIndex)); - return; - } - - QString type = element.attribute(aType); - if (type == vText) { // We don't have to care of the text object - if (element.hasAttribute(aActionMedia)) { - QString newRelative = cureNCopy(element.attribute(aActionMedia)); - element.setAttribute(aActionMedia, newRelative); - } - return; - } - QString newRelative = cureNCopy(element.attribute(aSrc)); - element.setAttribute(aSrc, newRelative); - } else if (tagName == tTeacherGuide) { - QDomElement nMediaElement = element.firstChildElement(tMedia); - while (!nMediaElement.isNull()) { - QString newRelative = cureNCopy(nMediaElement.attribute(aRelativePath)); - nMediaElement.setAttribute(aRelativePath, newRelative); - nMediaElement = nMediaElement.nextSiblingElement(tMedia); - } - } - } - - QString cureNCopy(const QString &relativePath, bool createNewUuid=true) - { - QString relative = relativePath; - if (createNewUuid) - { - QUuid newUuid = QUuid::createUuid(); - static const QRegularExpression bracedUuid("\\{.*\\}"); - QString newPath = relative.replace(bracedUuid, newUuid.toString()); - - cp_rf(mFromDir + "/" + relativePath, mToDir + "/" + newPath); - - return newPath; - } - else - { - cp_rf(mFromDir + "/" + relativePath, mToDir + "/" + relativePath); - return relativePath; - } - } - -private: - QString mFromDir; - QString mToDir; - int mFromIndex; - int mToIndex; -}; - -class UBForeighnObjectsHandlerPrivate { - UBForeighnObjectsHandlerPrivate(UBForeighnObjectsHandler *pq) - : q(pq) - { - } - -public: - void cure(const QUrl &dir) - { - Cleaner *cleaner = new Cleaner; - cleaner->cure(dir); - delete cleaner; - cleaner = 0; - } - - void copyPage (const QUrl &fromDir, int fromIndex, const QUrl &toDir, int toIndex) - { - PageCopier *copier = new PageCopier; - copier->copyPage(fromDir, fromIndex, toDir, toIndex); - delete copier; - copier = 0; - } - -private: - UBForeighnObjectsHandler *q; - friend class UBForeighnObjectsHandler; -}; - -UBForeighnObjectsHandler::UBForeighnObjectsHandler() - : d(new UBForeighnObjectsHandlerPrivate(this)) -{ - -} - -UBForeighnObjectsHandler::~UBForeighnObjectsHandler() -{ - delete d; -} - -void UBForeighnObjectsHandler::cure(const QList &dirs) -{ - foreach (QUrl dir, dirs) { - cure(dir); - } -} - -void UBForeighnObjectsHandler::cure(const QUrl &dir) -{ - d->cure(dir); -} - -void UBForeighnObjectsHandler::copyPage(const QUrl &fromDir, int fromIndex, const QUrl &toDir, int toIndex) -{ - d->copyPage(fromDir, fromIndex, toDir, toIndex); -} - diff --git a/src/core/UBForeignObjectsHandler.h b/src/core/UBForeignObjectsHandler.h deleted file mode 100644 index 7d03464b9..000000000 --- a/src/core/UBForeignObjectsHandler.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015-2022 Département de l'Instruction Publique (DIP-SEM) - * - * Copyright (C) 2013 Open Education Foundation - * - * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour - * l'Education Numérique en Afrique (GIP ENA) - * - * This file is part of OpenBoard. - * - * OpenBoard 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, version 3 of the License, - * with a specific linking exception for the OpenSSL project's - * "OpenSSL" library (or with modified versions of it that use the - * same license as the "OpenSSL" library). - * - * OpenBoard 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 OpenBoard. If not, see . - */ - -#ifndef UBFOREIGHNOBJECTSHANDLER_H -#define UBFOREIGHNOBJECTSHANDLER_H - -#include -#include -#include - -class UBForeighnObjectsHandlerPrivate; - -class UBForeighnObjectsHandler -{ -public: - UBForeighnObjectsHandler(); - ~UBForeighnObjectsHandler(); - - void cure(const QList &dirs); - void cure(const QUrl &dir); - - void copyPage(const QUrl &fromDir, int fromIndex, - const QUrl &toDir, int toIndex); - -private: - UBForeighnObjectsHandlerPrivate *d; - - friend class UBForeighnObjectsHandlerPrivate; -}; - -#endif // UBFOREIGHNOBJECTSHANDLER_H diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index 207735985..611750951 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -42,7 +42,6 @@ #include "core/UBApplication.h" #include "core/UBSettings.h" #include "core/UBSetting.h" -#include "core/UBForeignObjectsHandler.h" #include "document/UBDocumentProxy.h" @@ -960,41 +959,6 @@ void UBPersistenceManager::duplicateDocumentScene(std::shared_ptr from, int fromIndex, std::shared_ptr to, int toIndex) -{ - if (from == to && toIndex <= fromIndex) { - qDebug() << "operation is not supported" << Q_FUNC_INFO; - return; - } - - checkIfDocumentRepositoryExists(); - - for (int i = to->pageCount(); i > toIndex; i--) { - renamePage(to, i - 1, i); - mSceneCache.moveScene(to, i - 1, i); - } - - UBForeighnObjectsHandler hl; - hl.copyPage(QUrl::fromLocalFile(from->persistencePath()), fromIndex, - QUrl::fromLocalFile(to->persistencePath()), toIndex); - - to->incPageCount(); - - QString thumbTmp(from->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", fromIndex)); - QString thumbTo(to->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", toIndex)); - - QFile::remove(thumbTo); - QFile::copy(thumbTmp, thumbTo); - - Q_ASSERT(QFileInfo(thumbTmp).exists()); - Q_ASSERT(QFileInfo(thumbTo).exists()); - auto pix = std::make_shared(thumbTmp); - UBDocumentController *ctrl = UBApplication::documentController; - ctrl->TreeViewSelectionChanged(ctrl->firstSelectedTreeIndex(), QModelIndex()); - -// emit documentSceneCreated(to, toIndex + 1); -} - std::shared_ptr UBPersistenceManager::createDocumentSceneAt(std::shared_ptr proxy, int index, bool useUndoRedoStack) { diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h index 73d32b80f..06210dc0c 100644 --- a/src/core/UBPersistenceManager.h +++ b/src/core/UBPersistenceManager.h @@ -102,8 +102,6 @@ class UBPersistenceManager : public QObject virtual void duplicateDocumentScene(std::shared_ptr pDocumentProxy, int index); - virtual void copyDocumentScene(std::shared_ptrfrom, int fromIndex, std::shared_ptrto, int toIndex); - virtual void persistDocumentScene(std::shared_ptr pDocumentProxy, std::shared_ptr pScene, const int pSceneIndex, bool isAnAutomaticBackup = false, bool forceImmediateSaving = false); virtual std::shared_ptr createDocumentSceneAt(std::shared_ptr pDocumentProxy, int index, bool useUndoRedoStack = true); diff --git a/src/core/core.pri b/src/core/core.pri index 293e143e6..5732e8bdf 100644 --- a/src/core/core.pri +++ b/src/core/core.pri @@ -15,8 +15,7 @@ HEADERS += src/core/UB.h \ src/core/UBDownloadManager.h \ src/core/UBDownloadThread.h \ src/core/UBTextTools.h \ - src/core/UBPersistenceWorker.h \ - $$PWD/UBForeignObjectsHandler.h + src/core/UBPersistenceWorker.h SOURCES += src/core/main.cpp \ src/core/UBShortcutManager.cpp \ @@ -34,5 +33,4 @@ SOURCES += src/core/main.cpp \ src/core/UBDownloadManager.cpp \ src/core/UBDownloadThread.cpp \ src/core/UBTextTools.cpp \ - src/core/UBPersistenceWorker.cpp \ - $$PWD/UBForeignObjectsHandler.cpp + src/core/UBPersistenceWorker.cpp diff --git a/src/document/UBDocument.cpp b/src/document/UBDocument.cpp index 5dd87e7af..71ee0a522 100644 --- a/src/document/UBDocument.cpp +++ b/src/document/UBDocument.cpp @@ -78,18 +78,6 @@ void UBDocument::movePage(int fromIndex, int toIndex) mThumbnailScene->moveThumbnail(fromIndex, toIndex); } -void UBDocument::copyPage(int fromIndex, std::shared_ptr to, int toIndex) -{ - UBPersistenceManager::persistenceManager()->copyDocumentScene(mProxy, fromIndex, to, toIndex); - - const auto toDocument = findDocument(to); - - if (toDocument) - { - toDocument->mThumbnailScene->insertThumbnail(toIndex); - } -} - void UBDocument::insertPage(std::shared_ptr scene, int index, bool persist, bool deleting) { UBPersistenceManager::persistenceManager()->insertDocumentSceneAt(mProxy, scene, index, persist, deleting); diff --git a/src/document/UBDocument.h b/src/document/UBDocument.h index 7135e4765..672718d52 100644 --- a/src/document/UBDocument.h +++ b/src/document/UBDocument.h @@ -57,7 +57,6 @@ class UBDocument void deletePages(QList indexes); void duplicatePage(int index); void movePage(int fromIndex, int toIndex); - void copyPage(int fromIndex, std::shared_ptr to, int toIndex); void insertPage(std::shared_ptr scene, int index, bool persist = true, bool deleting = false); std::shared_ptr createPage(int index, bool useUndoRedoStack = true); void persistPage(std::shared_ptr scene, const int index, bool isAutomaticBackup = false, diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index c85a9d0ea..00a8f5c77 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -517,7 +517,7 @@ QVariant UBDocumentTreeModel::data(const QModelIndex &index, int role) const return QBrush(0xD9DFEB); } - if (mHighLighted.isValid() && index == mHighLighted) { + if (mHighLighted.isValid() && index.row() == mHighLighted.row()) { return QBrush(0x6682B5); } } @@ -684,109 +684,24 @@ QDateTime UBDocumentTreeModel::findCatalogCreationDate(UBDocumentTreeNode *node) QStringList UBDocumentTreeModel::mimeTypes() const { - QStringList types; - types << "text/uri-list" << "image/png" << "image/tiff" << "image/gif" << "image/jpeg"; + static const QStringList types{UBApplication::mimeTypeUniboardDocument}; return types; } QMimeData *UBDocumentTreeModel::mimeData (const QModelIndexList &indexes) const { - UBDocumentTreeMimeData *mimeData = new UBDocumentTreeMimeData(); - QList indexList; - QList urlList; + QModelIndexList indexList; - foreach (QModelIndex index, indexes) { - if (index.isValid()) { - indexList.append(index); - urlList.append(QUrl()); - } - } - -#if defined(Q_OS_OSX) - #if (QT_VERSION < QT_VERSION_CHECK(5, 15, 0)) - if (QOperatingSystemVersion::current().majorVersion() == 10 && QOperatingSystemVersion::current().minorVersion() < 15) /* <= Mojave */ - mimeData->setUrls(urlList); - #endif -#else - mimeData->setUrls(urlList); -#endif - mimeData->setIndexes(indexList); - - return mimeData; -} - -bool UBDocumentTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) -{ - if (action == Qt::IgnoreAction) { - return false; - } - - if (data->hasFormat(UBApplication::mimeTypeUniboardPage)) { - UBDocumentTreeNode *curNode = nodeFromIndex(index(row - 1, column, parent)); - std::shared_ptr targetDocProxy = curNode->proxyData(); - const UBMimeData *ubMime = qobject_cast (data); - if (!targetDocProxy || !ubMime || !ubMime->items().count()) { - qDebug() << "an error ocured while parsing " << UBApplication::mimeTypeUniboardPage; - return false; - } - - int total = ubMime->items().size(); - - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - - foreach (UBMimeDataItem sourceItem, ubMime->items()) - { - std::shared_ptr fromProxy = sourceItem.documentProxy(); - int fromIndex = sourceItem.sceneIndex(); - int toIndex = targetDocProxy->pageCount(); - - auto fromDocument = UBDocument::getDocument(fromProxy); - fromDocument->copyPage(fromIndex, targetDocProxy, toIndex); - } - - QApplication::restoreOverrideCursor(); - - UBApplication::showMessage(tr("%1 pages copied", "", total).arg(total), false); - - return true; - } - - const UBDocumentTreeMimeData *mimeData = qobject_cast(data); - if (!mimeData) { - qDebug() << "Incorrect mimeData, only internal one supported"; - return false; - } - - if (!parent.isValid()) { - return false; - } - - UBDocumentTreeNode *newParentNode = nodeFromIndex(parent); - - if (!newParentNode) { - qDebug() << "incorrect incoming parent node;"; - return false; - } - - QList incomingIndexes = mimeData->indexes(); - - foreach (QModelIndex curIndex, incomingIndexes) + for (const auto& index : indexes) { - //Issue N/C - NNE - 20140528 : use just the index on the first column - if(curIndex.column() == 0){ - QModelIndex clonedTopLevel = copyIndexToNewParent(curIndex, parent, action == Qt::MoveAction ? aReference : aContentCopy); - if (nodeFromIndex(curIndex) == mCurrentNode && action == Qt::MoveAction) { - emit currentIndexMoved(clonedTopLevel, curIndex); - } + // only add indexes for first column + if (index.isValid() && index.column() == 0) + { + indexList.append(index); } } - Q_UNUSED(action) - Q_UNUSED(row) - Q_UNUSED(column) - Q_UNUSED(parent) - - return true; + return new UBDocumentTreeMimeData(indexList); } bool UBDocumentTreeModel::removeRows(int row, int count, const QModelIndex &parent) @@ -1448,6 +1363,37 @@ bool UBDocumentTreeModel::nodeLessThan(const UBDocumentTreeNode *firstIndex, con return firstIndex->nodeName() < secondIndex->nodeName(); } +void UBDocumentTreeModel::setHighLighted(const QModelIndex& newHighLighted) +{ + QModelIndex from; + QModelIndex to; + + if (mHighLighted.isValid()) + { + from = mHighLighted.siblingAtColumn(0); + to = mHighLighted.siblingAtColumn(1); + }; + + if (newHighLighted.isValid()) + { + if (!from.isValid()) + { + from = newHighLighted.siblingAtColumn(0); + } + + to = newHighLighted.siblingAtColumn(1); + } + + mHighLighted = newHighLighted; + + if (from.row() > to.row()) + { + std::swap(from, to); + } + + emit dataChanged(from, to, {Qt::BackgroundRole}); +} + UBDocumentTreeModel::~UBDocumentTreeModel() { delete mRootNode; @@ -1522,89 +1468,69 @@ void UBDocumentTreeView::mousePressEvent(QMouseEvent *event) void UBDocumentTreeView::dragEnterEvent(QDragEnterEvent *event) { - QTreeView::dragEnterEvent(event); - event->accept(); - event->acceptProposedAction(); + if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardPage)) + { + // accept copying a page + event->setDropAction(Qt::CopyAction); + event->accept(); + } + else if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardDocument)) + { + // accept moving a document + event->setDropAction(Qt::MoveAction); + event->accept(); + } } void UBDocumentTreeView::dragLeaveEvent(QDragLeaveEvent *event) { Q_UNUSED(event); - UBDocumentTreeModel *docModel = 0; - - UBSortFilterProxyModel *proxy = dynamic_cast(model()); - - if(proxy){ - docModel = dynamic_cast(proxy->sourceModel()); - }else{ - docModel = dynamic_cast(model()); - } - - docModel->setHighLighted(QModelIndex()); + baseModel()->setHighLighted(QModelIndex()); update(); } void UBDocumentTreeView::dragMoveEvent(QDragMoveEvent *event) { - QModelIndex index; - if (selectedIndexes().count() > 0) + if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardPage)) { - index = selectedIndexes().first(); - } - #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) - QPoint eventPos = event->position().toPoint(); + QPoint eventPos = event->position().toPoint(); #else - QPoint eventPos = event->pos(); + QPoint eventPos = event->pos(); #endif - bool acceptIt = isAcceptable(index, indexAt(eventPos)); - - if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardPage)) { - UBSortFilterProxyModel *proxy = dynamic_cast(model()); - - UBDocumentTreeModel *docModel = 0; - - if(proxy){ - docModel = dynamic_cast(proxy->sourceModel()); - }else{ - docModel = dynamic_cast(model()); - } + UBDocumentTreeModel* docModel{baseModel()}; QModelIndex targetIndex = mapIndexToSource(indexAt(eventPos)); - if (!docModel || !docModel->isDocument(targetIndex) || docModel->inTrash(targetIndex)) { - event->ignore(); - event->setDropAction(Qt::IgnoreAction); + if (!targetIndex.isValid() || !docModel || !docModel->isDocument(targetIndex) || docModel->inTrash(targetIndex)) + { + event->ignore(visualRect(targetIndex)); if (docModel) { docModel->setHighLighted(QModelIndex()); } - - acceptIt = false; - } else { + } + else + { + event->setDropAction(Qt::CopyAction); + event->accept(visualRect(targetIndex)); docModel->setHighLighted(targetIndex); - acceptIt = true; } - updateIndexEnvirons(indexAt(eventPos)); } - QTreeView::dragMoveEvent(event); - - event->setAccepted(acceptIt); + else if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardDocument)) + { + event->accept(); + QTreeView::dragMoveEvent(event); + } } void UBDocumentTreeView::dropEvent(QDropEvent *event) { event->ignore(); event->setDropAction(Qt::IgnoreAction); - UBDocumentTreeModel *docModel = 0; - - //N/C - NNE - 20140408 - UBSortFilterProxyModel *proxy = dynamic_cast(model()); - if(proxy){ - docModel = dynamic_cast(proxy->sourceModel()); - } + UBDocumentTreeModel* docModel{baseModel()}; #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) QPoint eventPos = event->position().toPoint(); @@ -1612,9 +1538,6 @@ void UBDocumentTreeView::dropEvent(QDropEvent *event) QPoint eventPos = event->pos(); #endif QModelIndex targetIndex = mapIndexToSource(indexAt(eventPos)); - QModelIndexList dropIndex = mapIndexesToSource(selectionModel()->selectedRows(0)); - - bool isUBPage = event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardPage); //issue 1629 - NNE - 20131212 bool targetIsInTrash = docModel && (docModel->inTrash(targetIndex) || docModel->trashIndex() == targetIndex); @@ -1623,7 +1546,7 @@ void UBDocumentTreeView::dropEvent(QDropEvent *event) if (!targetIsInMyDocuments && !targetIsInTrash) return; - if (isUBPage) + if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardPage)) { std::shared_ptr targetDocProxy = docModel->proxyData(targetIndex); auto targetDocument = UBDocument::getDocument(targetDocProxy); @@ -1648,11 +1571,7 @@ void UBDocumentTreeView::dropEvent(QDropEvent *event) count++; UBApplication::showMessage(tr("Copying page %1/%2").arg(count).arg(total), true); - // FIXME code is similar to UBPersistenceManager::copyDocumentScene() - // PersistenceManaget works with UBForeignObjectHandler, while we here ask the scene for relative dependencies - // one is at file level, the other at scene level. I prefer scene level, as it avoids another SVG parser. - // Implement one single UBDocument::copyPage - + // FIXME Implement one single UBDocument::copyPage // TODO UB 4.x Move following code to some controller class std::shared_ptr scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(sourceItem.documentProxy(), fromIndex); if (scene) @@ -1689,20 +1608,24 @@ void UBDocumentTreeView::dropEvent(QDropEvent *event) UBApplication::showMessage(tr("%1 pages copied", "", total).arg(total), false); } - else + else if (event->mimeData()->hasFormat(UBApplication::mimeTypeUniboardDocument)) { - if(targetIsInTrash) + const auto* documentMimeData = dynamic_cast(event->mimeData()); + QModelIndexList dropIndex = documentMimeData->indexes(); + + if (targetIsInTrash) { UBApplication::documentController->moveIndexesToTrash(dropIndex, docModel); - }else{ + } + else + { docModel->moveIndexes(dropIndex, targetIndex); } } + UBSortFilterProxyModel *proxy = dynamic_cast(model()); expand(proxy->mapFromSource(targetIndex)); - QTreeView::dropEvent(event); - UBApplication::documentController->pageSelectionChanged(); } @@ -1716,6 +1639,12 @@ void UBDocumentTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int sta QTreeView::rowsAboutToBeRemoved(parent, start, end); } +UBDocumentTreeModel* UBDocumentTreeView::baseModel() const +{ + UBSortFilterProxyModel *proxy = dynamic_cast(model()); + return dynamic_cast(proxy ? proxy->sourceModel() : model()); +} + bool UBDocumentTreeView::isAcceptable(const QModelIndex &dragIndex, const QModelIndex &atIndex) { QModelIndex dragIndexSource = mapIndexToSource(dragIndex); @@ -1732,14 +1661,6 @@ Qt::DropAction UBDocumentTreeView::acceptableAction(const QModelIndex &dragIndex return Qt::MoveAction; } -void UBDocumentTreeView::updateIndexEnvirons(const QModelIndex &index) -{ - QRect updateRect = visualRect(index); - const int multipler = 3; - updateRect.adjust(0, -updateRect.height() * multipler, 0, updateRect.height() * multipler); - update(updateRect); -} - //N/C - NNE - 20140404 QModelIndex UBDocumentTreeView::mapIndexToSource(const QModelIndex &index) { @@ -1751,23 +1672,6 @@ QModelIndex UBDocumentTreeView::mapIndexToSource(const QModelIndex &index) return index; } - -QModelIndexList UBDocumentTreeView::mapIndexesToSource(const QModelIndexList &indexes) -{ - UBSortFilterProxyModel *proxy = dynamic_cast(model()); - - if(proxy){ - QModelIndexList list; - - for(int i = 0; i < indexes.size(); i++){ - list.push_back(proxy->mapToSource(indexes.at(i))); - } - - return list; - } - - return indexes; -} //N/C - NNE - 20140404 : END UBDocumentTreeItemDelegate::UBDocumentTreeItemDelegate(QObject *parent) @@ -2267,6 +2171,7 @@ void UBDocumentController::setupViews() mDocumentUI->documentTreeView->setItemDelegate(new UBDocumentTreeItemDelegate(this)); mDocumentUI->documentTreeView->setDragEnabled(true); mDocumentUI->documentTreeView->setAcceptDrops(true); + mDocumentUI->documentTreeView->setDefaultDropAction(Qt::MoveAction); mDocumentUI->documentTreeView->viewport()->setAcceptDrops(true); mDocumentUI->documentTreeView->setDropIndicatorShown(true); mDocumentUI->documentTreeView->header()->setStretchLastSection(false); @@ -4036,3 +3941,14 @@ void UBDocumentController::clearThumbnailsSelection() mDocumentUI->thumbnailWidget->clearSelection(); pageSelectionChanged(); } + +UBDocumentTreeMimeData::UBDocumentTreeMimeData(const QModelIndexList& pIndexes) + : mIndexes{pIndexes} +{ + setData(UBApplication::mimeTypeUniboardDocument, {}); +} + +QModelIndexList UBDocumentTreeMimeData::indexes() const +{ + return mIndexes; +} diff --git a/src/document/UBDocumentController.h b/src/document/UBDocumentController.h index bd094bbb0..07513b831 100644 --- a/src/document/UBDocumentController.h +++ b/src/document/UBDocumentController.h @@ -192,14 +192,12 @@ class UBDocumentTreeModel : public QAbstractItemModel { Qt::DropActions supportedDropActions() const {return Qt::MoveAction | Qt::CopyAction;} QStringList mimeTypes() const; QMimeData *mimeData (const QModelIndexList &indexes) const; - bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); bool removeRows(int row, int count, const QModelIndex &parent); bool containsDocuments(const QModelIndex& index); QModelIndex indexForNode(UBDocumentTreeNode *pNode) const; QPersistentModelIndex persistentIndexForNode(UBDocumentTreeNode *pNode); -// bool insertRow(int row, const QModelIndex &parent); QPersistentModelIndex copyIndexToNewParent(const QModelIndex &source, const QModelIndex &newParent, eCopyMode pMode = aReference); @@ -241,7 +239,7 @@ class UBDocumentTreeModel : public QAbstractItemModel { QPersistentModelIndex untitledDocumentsIndex() const {return mMyDocuments;} UBDocumentTreeNode *nodeFromIndex(const QModelIndex &pIndex) const; static bool nodeLessThan(const UBDocumentTreeNode *firstIndex, const UBDocumentTreeNode *secondIndex); - void setHighLighted(const QModelIndex &newHighLighted) {mHighLighted = newHighLighted;} + void setHighLighted(const QModelIndex &newHighLighted); QModelIndex highLighted() {return mHighLighted;} std::shared_ptr findDocumentByFolderName(QString folderName) const; std::shared_ptr findDocumentByFolderName(UBDocumentTreeNode* node, QString folderName) const; @@ -291,12 +289,12 @@ class UBDocumentTreeMimeData : public QMimeData { Q_OBJECT - public: - QList indexes() const {return mIndexes;} - void setIndexes (const QList &pIndexes) {mIndexes = pIndexes;} +public: + UBDocumentTreeMimeData(const QModelIndexList& pIndexes); + QModelIndexList indexes() const; - private: - QList mIndexes; +private: + QModelIndexList mIndexes; }; class UBDocumentTreeView : public QTreeView @@ -308,7 +306,6 @@ class UBDocumentTreeView : public QTreeView //N/C - NNE - 20140404 QModelIndex mapIndexToSource(const QModelIndex &index); - QModelIndexList mapIndexesToSource(const QModelIndexList &indexes); public slots: void setSelectedAndExpanded(const QModelIndex &pIndex, bool pExpand = true, bool pEdit = false); @@ -329,8 +326,8 @@ public slots: private: bool isAcceptable(const QModelIndex &dragIndex, const QModelIndex &atIndex); + UBDocumentTreeModel* baseModel() const; Qt::DropAction acceptableAction(const QModelIndex &dragIndex, const QModelIndex &atIndex); - void updateIndexEnvirons(const QModelIndex &index); }; class UBValidator : public QValidator diff --git a/src/gui/UBDocumentThumbnailWidget.cpp b/src/gui/UBDocumentThumbnailWidget.cpp index 9b60c368b..b4ea91d4f 100644 --- a/src/gui/UBDocumentThumbnailWidget.cpp +++ b/src/gui/UBDocumentThumbnailWidget.cpp @@ -107,7 +107,7 @@ void UBDocumentThumbnailWidget::mouseMoveEvent(QMouseEvent *event) drag->setPixmap(sceneItem->pixmap().scaledToWidth(100)); drag->setHotSpot(QPoint(drag->pixmap().width()/2, drag->pixmap().height() / 2)); - drag->exec(Qt::MoveAction); + drag->exec({Qt::MoveAction, Qt::CopyAction}); } UBDocumentThumbnailsView::mouseMoveEvent(event);