Commit b4bb6f05 authored by Claudio Valerio's avatar Claudio Valerio

removed cff support

parent 5cea797e
...@@ -55,11 +55,6 @@ DEPENDPATH += src/pdf-merger ...@@ -55,11 +55,6 @@ DEPENDPATH += src/pdf-merger
INCLUDEPATH += src/pdf-merger INCLUDEPATH += src/pdf-merger
include(src/pdf-merger/pdfMerger.pri) include(src/pdf-merger/pdfMerger.pri)
#plugins
include(plugins/plugins.pri)
INCLUDEPATH += plugins/cffadaptor/src
#ThirdParty #ThirdParty
DEPENDPATH += $$THIRD_PARTY_PATH/quazip/ DEPENDPATH += $$THIRD_PARTY_PATH/quazip/
INCLUDEPATH += $$THIRD_PARTY_PATH/quazip/ INCLUDEPATH += $$THIRD_PARTY_PATH/quazip/
...@@ -385,7 +380,6 @@ linux-g++* { ...@@ -385,7 +380,6 @@ linux-g++* {
} }
RESOURCES += resources/OpenBoard.qrc RESOURCES += resources/OpenBoard.qrc
RESOURCES += plugins/cffadaptor/resources/resources.qrc
# When adding a translation here, also add it in the macx part # When adding a translation here, also add it in the macx part
TRANSLATIONS = resources/i18n/OpenBoard_en.ts \ TRANSLATIONS = resources/i18n/OpenBoard_en.ts \
......
#-------------------------------------------------
#
# Project created by QtCreator 2012-02-14T13:30:14
#
#-------------------------------------------------
TARGET = CFF_Adaptor
TEMPLATE = lib
win32: SUB_DIR = win32
macx: SUB_DIR = macx
linux-g++: SUB_DIR = linux
linux-g++-32: SUB_DIR = linux
linux-g++-64: SUB_DIR = linux
THIRD_PARTY_PATH = ../../../Sankore-ThirdParty
QUAZIP_DIR = "$$PWD/../../../Sankore-ThirdParty/quazip/quazip-0.3"
BUILD_DIR = build/$$SUB_DIR
CONFIG(debug, debug|release):BUILD_DIR = $$BUILD_DIR/debug
CONFIG(release, debug|release) {
BUILD_DIR = $$BUILD_DIR/release
CONFIG += warn_off
}
win32{
CONFIG += dll
}
OBJECTS_DIR = $$BUILD_DIR/objects
MOC_DIR = $$BUILD_DIR/moc
DESTDIR = $$BUILD_DIR/lib
RCC_DIR = $$BUILD_DIR/rcc
SANKORE_DIR = ../..
win32:{
QMAKE_POST_LINK += copy $$replace(DESTDIR,/,\\)\\CFF_Adaptor.dll" $$replace(SANKORE_DIR,/,\\)\\CFF_Adaptor.dll /y"
}
macx:{
QMAKE_POST_LINK += bash postScript_mac.sh "$$DESTDIR" "$$SANKORE_DIR/$$BUILD_DIR/product/Open-Sankore.app/Contents/MacOS"
}
LIBS += "-L$$THIRD_PARTY_PATH/quazip/lib/$$SUB_DIR" "-lquazip"
QT += xml xmlpatterns core
QT += gui
QT += svg
DEFINES += UBCFFADAPTOR_LIBRARY
DEFINES += NO_THIRD_PARTY_WARNINGS
INCLUDEPATH += src
DEPENDPATH += $$THIRD_PARTY_PATH/quazip/
INCLUDEPATH += $$THIRD_PARTY_PATH/quazip/
include($$THIRD_PARTY_PATH/quazip/quazip.pri)
SOURCES += \
src/UBCFFAdaptor.cpp
HEADERS +=\
$$PWD/../../src/globals/UBGlobals.h \
src/UBCFFAdaptor.h \
src/UBCFFAdaptor_global.h \
src/UBCFFConstants.h
RESOURCES += \
resources/resources.qrc
\ No newline at end of file
#!/bin/bash
SOURCE=$1
DESTINATION=$2
mkdir -p $DESTINATION
cp -R $SOURCE/ $DESTINATION
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg version="1.2" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="26px" height="26px" viewBox="0 0 26 26" xml:space="preserve">
<circle fill="#CCCCCC" cx="13" cy="13" r="13"/>
<circle fill="#999999" cx="13" cy="13" r="11"/>
<rect x="7" y="9" fill="#FFFFFF" width="6" height="8"/>
<polygon fill="#FFFFFF" points="10,11 10,15 17,21 17,5 "/>
</svg>
<RCC>
<qresource prefix="/">
<file>images/soundOn.svg</file>
</qresource>
</RCC>
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "UBCFFAdaptor.h"
#include <QtCore>
#include <QtXml>
#include <QTransform>
#include <QGraphicsItem>
#include <QSvgRenderer>
#include <QPainter>
#include "UBGlobals.h"
#include "UBCFFConstants.h"
THIRD_PARTY_WARNINGS_DISABLE
#include "quazip.h"
#include "quazipfile.h"
#include "quazipfileinfo.h"
THIRD_PARTY_WARNINGS_ENABLE
UBCFFAdaptor::UBCFFAdaptor()
{}
bool UBCFFAdaptor::convertUBZToIWB(const QString &from, const QString &to)
{
qDebug() << "starting converion from" << from << "to" << to;
QString source = QString();
if (QFileInfo(from).isDir() && QFile::exists(from)) {
qDebug() << "File specified is dir, continuing convertion";
source = from;
} else {
source = uncompressZip(from);
if (!source.isNull()) qDebug() << "File specified is zip file. Uncompressed to tmp dir, continuing convertion";
}
if (source.isNull()) {
qDebug() << "File specified is not a dir or a zip file, stopping covretion";
return false;
}
QString tmpDestination = createNewTmpDir();
if (tmpDestination.isNull()) {
qDebug() << "can't create temp destination folder. Stopping parsing...";
return false;
}
UBToCFFConverter tmpConvertrer(source, tmpDestination);
if (!tmpConvertrer) {
qDebug() << "The convertrer class is invalid, stopping conversion. Error message" << tmpConvertrer.lastErrStr();
return false;
}
bool bParceRes = tmpConvertrer.parse();
mConversionMessages << tmpConvertrer.getMessages();
if (!bParceRes) {
return false;
}
if (!compressZip(tmpDestination, to))
qDebug() << "error in compression";
//Cleanning tmp souces in filesystem
if (!QFileInfo(from).isDir())
if (!freeDir(source))
qDebug() << "can't delete tmp directory" << QDir(source).absolutePath() << "try to delete them manually";
if (!freeDir(tmpDestination))
qDebug() << "can't delete tmp directory" << QDir(tmpDestination).absolutePath() << "try to delete them manually";
return true;
}
QString UBCFFAdaptor::uncompressZip(const QString &zipFile)
{
QuaZip zip(zipFile);
if(!zip.open(QuaZip::mdUnzip)) {
qWarning() << "Import failed. Cause zip.open(): " << zip.getZipError();
return QString();
}
zip.setFileNameCodec("UTF-8");
QuaZipFileInfo info;
QuaZipFile file(&zip);
//create unique cff document root fodler
QString documentRootFolder = createNewTmpDir();
if (documentRootFolder.isNull()) {
qDebug() << "can't create tmp directory for zip file" << zipFile;
return QString();
}
QDir rootDir(documentRootFolder);
QFile out;
char c;
bool allOk = true;
for(bool more = zip.goToFirstFile(); more; more=zip.goToNextFile()) {
if(!zip.getCurrentFileInfo(&info)) {
qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError();
allOk = false;
break;
}
if(!file.open(QIODevice::ReadOnly)) {
allOk = false;
break;
}
if(file.getZipError()!= UNZ_OK) {
qWarning() << "Import failed. Cause: file.getFileName(): " << zip.getZipError();
allOk = false;
break;
}
QString newFileName = documentRootFolder + "/" + file.getActualFileName();
QFileInfo newFileInfo(newFileName);
rootDir.mkpath(newFileInfo.absolutePath());
out.setFileName(newFileName);
out.open(QIODevice::WriteOnly);
while(file.getChar(&c))
out.putChar(c);
out.close();
if(file.getZipError()!=UNZ_OK) {
qWarning() << "Import failed. Cause: " << zip.getZipError();
allOk = false;
break;
}
if(!file.atEnd()) {
qWarning() << "Import failed. Cause: read all but not EOF";
allOk = false;
break;
}
file.close();
if(file.getZipError()!=UNZ_OK) {
qWarning() << "Import failed. Cause: file.close(): " << file.getZipError();
allOk = false;
break;
}
}
if (!allOk) {
out.close();
file.close();
zip.close();
return QString();
}
if(zip.getZipError()!=UNZ_OK) {
qWarning() << "Import failed. Cause: zip.close(): " << zip.getZipError();
return QString();
}
return documentRootFolder;
}
bool UBCFFAdaptor::compressZip(const QString &source, const QString &destination)
{
QDir toDir = QFileInfo(destination).dir();
if (!toDir.exists())
if (!QDir().mkpath(toDir.absolutePath())) {
qDebug() << "can't create destination folder to uncompress file";
return false;
}
QuaZip zip(destination);
zip.setFileNameCodec("UTF-8");
if(!zip.open(QuaZip::mdCreate)) {
qDebug("Export failed. Cause: zip.open(): %d", zip.getZipError());
return false;
}
QuaZipFile outZip(&zip);
QFileInfo sourceInfo(source);
if (sourceInfo.isDir()) {
if (!compressDir(QFileInfo(source).absoluteFilePath(), "", &outZip))
return false;
} else if (sourceInfo.isFile()) {
if (!compressFile(QFileInfo(source).absoluteFilePath(), "", &outZip))
return false;
}
return true;
}
bool UBCFFAdaptor::compressDir(const QString &dirName, const QString &parentDir, QuaZipFile *outZip)
{
QFileInfoList dirFiles = QDir(dirName).entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
QListIterator<QFileInfo> iter(dirFiles);
while (iter.hasNext()) {
QFileInfo curFile = iter.next();
if (curFile.isDir()) {
if (!compressDir(curFile.absoluteFilePath(), parentDir + curFile.fileName() + "/", outZip)) {
qDebug() << "error at compressing dir" << curFile.absoluteFilePath();
return false;
}
} else if (curFile.isFile()) {
if (!compressFile(curFile.absoluteFilePath(), parentDir, outZip)) {
return false;
}
}
}
return true;
}
bool UBCFFAdaptor::compressFile(const QString &fileName, const QString &parentDir, QuaZipFile *outZip)
{
QFile sourceFile(fileName);
if(!sourceFile.open(QIODevice::ReadOnly)) {
qDebug() << "Compression of file" << sourceFile.fileName() << " failed. Cause: inFile.open(): " << sourceFile.errorString();
return false;
}
if(!outZip->open(QIODevice::WriteOnly, QuaZipNewInfo(parentDir + QFileInfo(fileName).fileName(), sourceFile.fileName()))) {
qDebug() << "Compression of file" << sourceFile.fileName() << " failed. Cause: outFile.open(): " << outZip->getZipError();
sourceFile.close();
return false;
}
outZip->write(sourceFile.readAll());
if(outZip->getZipError() != UNZ_OK) {
qDebug() << "Compression of file" << sourceFile.fileName() << " failed. Cause: outFile.write(): " << outZip->getZipError();
sourceFile.close();
outZip->close();
return false;
}
if(outZip->getZipError() != UNZ_OK)
{
qWarning() << "Compression of file" << sourceFile.fileName() << " failed. Cause: outFile.close(): " << outZip->getZipError();
sourceFile.close();
outZip->close();
return false;
}
outZip->close();
sourceFile.close();
return true;
}
QString UBCFFAdaptor::createNewTmpDir()
{
int tmpNumber = 0;
QDir systemTmp = QDir::temp();
while (true) {
QString dirName = QString("CFF_adaptor_filedata_store%1.%2")
.arg(QDateTime::currentDateTime().toString("dd_MM_yyyy_HH-mm"))
.arg(tmpNumber++);
if (!systemTmp.exists(dirName)) {
if (systemTmp.mkdir(dirName)) {
QString result = systemTmp.absolutePath() + "/" + dirName;
tmpDirs.append(result);
return result;
} else {
qDebug() << "Can't create temporary dir maybe due to permissions";
return QString();
}
} else if (tmpNumber == 10) {
qWarning() << "Import failed. Failed to create temporary file ";
return QString();
}
tmpNumber++;
}
return QString();
}
bool UBCFFAdaptor::deleteDir(const QString& pDirPath) const
{
if (pDirPath == "" || pDirPath == "." || pDirPath == "..")
return false;
QDir dir(pDirPath);
if (dir.exists())
{
foreach(QFileInfo dirContent, dir.entryInfoList(QDir::Files | QDir::Dirs
| QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, QDir::Name))
{
if (dirContent.isDir())
{
deleteDir(dirContent.absoluteFilePath());
}
else
{
if (!dirContent.dir().remove(dirContent.fileName()))
{
return false;
}
}
}
}
return dir.rmdir(pDirPath);
}
QList<QString> UBCFFAdaptor::getConversionMessages()
{
return mConversionMessages;
}
bool UBCFFAdaptor::freeDir(const QString &dir)
{
bool result = true;
if (!deleteDir(dir))
result = false;
tmpDirs.removeAll(QDir(dir).absolutePath());
return result;
}
void UBCFFAdaptor::freeTmpDirs()
{
foreach (QString dir, tmpDirs)
freeDir(dir);
}
UBCFFAdaptor::~UBCFFAdaptor()
{
freeTmpDirs();
}
UBCFFAdaptor::UBToCFFConverter::UBToCFFConverter(const QString &source, const QString &destination)
{
sourcePath = source;
destinationPath = destination;
errorStr = noErrorMsg;
mDataModel = new QDomDocument;
mDocumentToWrite = new QDomDocument;
mDocumentToWrite->setContent(QString("<doc></doc>"));
mIWBContentWriter = new QXmlStreamWriter;
mIWBContentWriter->setAutoFormatting(true);
iwbSVGItemsAttributes.insert(tIWBImage, iwbSVGImageAttributes);
iwbSVGItemsAttributes.insert(tIWBVideo, iwbSVGVideoAttributes);
iwbSVGItemsAttributes.insert(tIWBText, iwbSVGTextAttributes);
iwbSVGItemsAttributes.insert(tIWBTextArea, iwbSVGTextAreaAttributes);
iwbSVGItemsAttributes.insert(tIWBPolyLine, iwbSVGPolyLineAttributes);
iwbSVGItemsAttributes.insert(tIWBPolygon, iwbSVGPolygonAttributes);
iwbSVGItemsAttributes.insert(tIWBRect, iwbSVGRectAttributes);
iwbSVGItemsAttributes.insert(tIWBLine, iwbSVGLineAttributes);
iwbSVGItemsAttributes.insert(tIWBTspan, iwbSVGTspanAttributes);
}
bool UBCFFAdaptor::UBToCFFConverter::parse()
{
if(!isValid()) {
qDebug() << "document metadata is not valid. Can't parse";
return false;
}
qDebug() << "begin parsing ubz";
QFile outFile(contentIWBFileName());
if (!outFile.open(QIODevice::WriteOnly| QIODevice::Text)) {
qDebug() << "can't open output file for writing";
errorStr = "createXMLOutputPatternError";
return false;
}
mIWBContentWriter->setDevice(&outFile);
mIWBContentWriter->writeStartDocument();
mIWBContentWriter->writeStartElement(tIWBRoot);
fillNamespaces();
mIWBContentWriter->writeAttribute(aIWBVersion, avIWBVersionNo);
if (!parseMetadata()) {
if (errorStr == noErrorMsg)
errorStr = "MetadataParsingError";
outFile.close();
return false;
}
if (!parseContent()) {
if (errorStr == noErrorMsg)
errorStr = "ContentParsingError";
outFile.close();
return false;
}
mIWBContentWriter->writeEndElement();
mIWBContentWriter->writeEndDocument();
outFile.close();
qDebug() << "finished with success";
return true;
}
bool UBCFFAdaptor::UBToCFFConverter::parseMetadata()
{
int errorLine, errorColumn;
QFile metaDataFile(sourcePath + "/" + fMetadata);
if (!metaDataFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
errorStr = "can't open" + QFileInfo(sourcePath + "/" + fMetadata).absoluteFilePath();
qDebug() << errorStr;
return false;
} else if (!mDataModel->setContent(metaDataFile.readAll(), true, &errorStr, &errorLine, &errorColumn)) {
qWarning() << "Error:Parseerroratline" << errorLine << ","
<< "column" << errorColumn << ":" << errorStr;
return false;
}
QDomElement nextInElement = mDataModel->documentElement();
nextInElement = nextInElement.firstChildElement(tDescription);
if (!nextInElement.isNull()) {
mIWBContentWriter->writeStartElement(iwbNS, tIWBMeta);
mIWBContentWriter->writeAttribute(aIWBName, aCreator);
mIWBContentWriter->writeAttribute(aIWBContent, avCreator);
mIWBContentWriter->writeEndElement();
mIWBContentWriter->writeStartElement(iwbNS, tIWBMeta);
mIWBContentWriter->writeAttribute(aIWBName, aOwner);
mIWBContentWriter->writeAttribute(aIWBContent, avOwner);
mIWBContentWriter->writeEndElement();
mIWBContentWriter->writeStartElement(iwbNS, tIWBMeta);
mIWBContentWriter->writeAttribute(aIWBName, aDescription);
mIWBContentWriter->writeAttribute(aIWBContent, avDescription);
mIWBContentWriter->writeEndElement();
mIWBContentWriter->writeStartElement(iwbNS, tIWBMeta);
mIWBContentWriter->writeAttribute(aIWBName, aAbout);
mIWBContentWriter->writeAttribute(aIWBContent, nextInElement.attribute(aAbout));
mIWBContentWriter->writeEndElement();
nextInElement = nextInElement.firstChildElement();
while (!nextInElement.isNull()) {
QString textContent = nextInElement.text();
if (!textContent.trimmed().isEmpty()) {
if (nextInElement.tagName() == tUBZSize) { //taking main viewbox rect since for CFF specificaton we have static viewbox
QSize tmpSize = getSVGDimentions(nextInElement.text());
if (!tmpSize.isNull()) {
mSVGSize = tmpSize;
} else {
qDebug() << "can't interpret svg section size";
errorStr = "InterpretSvgSizeError";
return false;
}
} else {
mIWBContentWriter->writeStartElement(iwbNS, tIWBMeta);
mIWBContentWriter->writeAttribute(aIWBName, nextInElement.tagName());
mIWBContentWriter->writeAttribute(aIWBContent, textContent);
mIWBContentWriter->writeEndElement();
}
}
nextInElement = nextInElement.nextSiblingElement();
}
}
metaDataFile.close();
return true;
}
bool UBCFFAdaptor::UBToCFFConverter::parseContent() {
QDir sourceDir(sourcePath);
QStringList fileFilters;
fileFilters << QString(pageAlias + "???." + pageFileExtentionUBZ);
QStringList pageList = sourceDir.entryList(fileFilters, QDir::Files, QDir::Name | QDir::IgnoreCase);
QDomElement svgDocumentSection = mDataModel->createElementNS(svgIWBNS, ":"+tSvg);
if (!pageList.count()) {
qDebug() << "can't find any content file";
errorStr = "ErrorContentFile";
return false;
} else
{
QDomElement pageset = parsePageset(pageList);
if (pageset.isNull())
return false;
else
svgDocumentSection.appendChild(pageset);
}
if (QRect() == mViewbox)
{
mViewbox.setRect(0,0, mSVGSize.width(), mSVGSize.height());
}
svgDocumentSection.setAttribute(aIWBViewBox, rectToIWBAttr(mViewbox));
svgDocumentSection.setAttribute(aWidth, QString("%1").arg(mViewbox.width()));
svgDocumentSection.setAttribute(aHeight, QString("%1").arg(mViewbox.height()));
writeQDomElementToXML(svgDocumentSection);
if (!writeExtendedIwbSection()) {
if (errorStr == noErrorMsg)
errorStr = "writeExtendedIwbSectionError";
return false;
}
return true;
}
QDomElement UBCFFAdaptor::UBToCFFConverter::parsePage(const QString &pageFileName)
{
qDebug() << "begin parsing page" + pageFileName;
mSvgElements.clear(); //clean Svg elements map before parsing new page
int errorLine, errorColumn;
QFile pageFile(sourcePath + "/" + pageFileName);
if (!pageFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "can't open file" << pageFileName << "for reading";
return QDomElement();
} else if (!mDataModel->setContent(pageFile.readAll(), true, &errorStr, &errorLine, &errorColumn)) {
qWarning() << "Error:Parseerroratline" << errorLine << ","
<< "column" << errorColumn << ":" << errorStr;
pageFile.close();
return QDomElement();
}
QDomElement page;
QDomElement group;
QDomElement nextTopElement = mDataModel->firstChildElement();
while (!nextTopElement.isNull()) {
QString tagname = nextTopElement.tagName();
if (tagname == tSvg) {
page = parseSvgPageSection(nextTopElement);
if (page.isNull()) {
qDebug() << "The page is empty.";
pageFile.close();
return QDomElement();
}
} else if (tagname == tUBZGroups) {
group = parseGroupsPageSection(nextTopElement);
if (group.isNull()) {
qDebug() << "Page doesn't contains any groups.";
pageFile.close();
return QDomElement();
}
}
nextTopElement = nextTopElement.nextSiblingElement();
}
pageFile.close();
return page.hasChildNodes() ? page : QDomElement();
}
QDomElement UBCFFAdaptor::UBToCFFConverter::parsePageset(const QStringList &pageFileNames)
{
QMultiMap<int, QDomElement> pageList;
int iPageNo = 1;
QStringListIterator curPage(pageFileNames);
while (curPage.hasNext()) {
QString curPageFile = curPage.next();
QDomElement iterElement = parsePage(curPageFile);
if (!iterElement.isNull())
{
iterElement.setAttribute(tId, iPageNo);
addSVGElementToResultModel(iterElement, pageList, iPageNo);
iPageNo++;
}
else
return QDomElement();
}
if (!pageList.count())
return QDomElement();
QDomElement svgPagesetElement = mDocumentToWrite->createElementNS(svgIWBNS,":"+ tIWBPageSet);
QMapIterator<int, QDomElement> nextSVGElement(pageList);
nextSVGElement.toFront();
while (nextSVGElement.hasNext())
svgPagesetElement.appendChild(nextSVGElement.next().value());
return svgPagesetElement.hasChildNodes() ? svgPagesetElement : QDomElement();
}
QDomElement UBCFFAdaptor::UBToCFFConverter::parseSvgPageSection(const QDomElement &element)
{
//we don't know about page number, so return QDomElement.
//Parsing top level tag attributes
//getting current page viewbox to be able to convert coordinates to global viewbox parameter
if (element.hasAttribute(aUBZViewBox)) {
setViewBox(getViewboxRect(element.attribute(aUBZViewBox)));
}
QMultiMap<int, QDomElement> svgElements;
QDomElement svgElementPart = mDocumentToWrite->createElementNS(svgIWBNS,":"+ tIWBPage);
if (element.hasAttribute(aDarkBackground)) {
createBackground(element, svgElements);
}
//Parsing svg children attributes
// Elements can know about its layer, so it must add result QDomElements to ordrered list.
QDomElement nextElement = element.firstChildElement();
while (!nextElement.isNull()) {
QString tagName = nextElement.tagName();
if (tagName == tUBZG) parseSVGGGroup(nextElement, svgElements);
else if (tagName == tUBZImage) parseUBZImage(nextElement, svgElements);
else if (tagName == tUBZVideo) parseUBZVideo(nextElement, svgElements);
else if (tagName == tUBZAudio) parseUBZAudio(nextElement, svgElements);
else if (tagName == tUBZForeignObject) parseForeignObject(nextElement, svgElements);
else if (tagName == tUBZLine) parseUBZLine(nextElement, svgElements);
else if (tagName == tUBZPolygon) parseUBZPolygon(nextElement, svgElements);
else if (tagName == tUBZPolyline) parseUBZPolyline(nextElement, svgElements);
else if (tagName == tUBZGroups) parseGroupsPageSection(nextElement);
nextElement = nextElement.nextSiblingElement();
}
if (0 == svgElements.count())
return QDomElement();
// to do:
// there we must to sort elements (take elements from list and assign parent ordered like in parseSVGGGroup)
// we returns just element because we don't care about layer.
QMapIterator<int, QDomElement> nextSVGElement(svgElements);
nextSVGElement.toFront();
while (nextSVGElement.hasNext())
svgElementPart.appendChild(nextSVGElement.next().value());
return svgElementPart.hasChildNodes() ? svgElementPart : QDomElement();
}
void UBCFFAdaptor::UBToCFFConverter::writeQDomElementToXML(const QDomNode &node)
{
if (!node.isNull()) {
if (node.isText())
mIWBContentWriter->writeCharacters(node.nodeValue());
else {
mIWBContentWriter->writeStartElement(node.namespaceURI(), node.toElement().tagName());
for (int i = 0; i < node.toElement().attributes().count(); i++) {
QDomAttr attr = node.toElement().attributes().item(i).toAttr();
mIWBContentWriter->writeAttribute(attr.name(), attr.value());
}
QDomNode child = node.firstChild();
while(!child.isNull()) {
writeQDomElementToXML(child);
child = child.nextSibling();
}
mIWBContentWriter->writeEndElement();
}
}
}
bool UBCFFAdaptor::UBToCFFConverter::writeExtendedIwbSection()
{
if (!mExtendedElements.count()) {
qDebug() << "extended iwb content list is empty";
errorStr = "EmptyExtendedIwbSectionContentError";
return false;
}
QListIterator<QDomElement> nextExtendedIwbElement(mExtendedElements);
while (nextExtendedIwbElement.hasNext()) {
writeQDomElementToXML(nextExtendedIwbElement.next());
//TODO write iwb extended element to mIWBContentWriter
}
return true;
}
// extended element options
// editable, background, locked are supported for now
QDomElement UBCFFAdaptor::UBToCFFConverter::parseGroupsPageSection(const QDomElement &groupRoot)
{
// First sankore side implementation needed. TODO in Sankore 1.5
if (!groupRoot.hasChildNodes()) {
qDebug() << "Group root is empty";
return QDomElement();
}
QDomElement groupElement = groupRoot.firstChildElement();
while (!groupElement.isNull()) {
QDomElement extendedElement = mDataModel->createElementNS(iwbNS, groupElement.tagName());
QDomElement groupChildElement = groupElement.firstChildElement();
while (!groupChildElement.isNull()) {
QDomElement extSubElement = mDataModel->createElementNS(iwbNS, groupChildElement.tagName());
extSubElement.setAttribute(aRef, groupChildElement.attribute(aID, QUuid().toString()));
extendedElement.appendChild(extSubElement);
groupChildElement = groupChildElement.nextSiblingElement();
}
mExtendedElements.append(extendedElement);
groupElement = groupElement.nextSiblingElement();
}
qDebug() << "parsing ubz group section";
return groupRoot;
}
QString UBCFFAdaptor::UBToCFFConverter::getDstContentFolderName(const QString &elementType)
{
QString sRet;
QString sDstContentFolderName;
// widgets must be saved as .png images.
if ((tIWBImage == elementType) || (tUBZForeignObject == elementType))
sDstContentFolderName = cfImages;
else
if (tIWBVideo == elementType)
sDstContentFolderName = cfVideos;
else
if (tIWBAudio == elementType)
sDstContentFolderName = cfAudios;
sRet = sDstContentFolderName;
return sRet;
}
QString UBCFFAdaptor::UBToCFFConverter::getSrcContentFolderName(QString href)
{
QString sRet;
QStringList ls = href.split("/");
for (int i = 0; i < ls.count()-1; i++)
{
QString sPart = ls.at(i);
if (ubzContentFolders.contains(sPart))
{
sRet = sPart;
}
}
// if (0 < ls.count())
// sRet = ls.at(ls.count()-1);
//
// sRet = href.remove(sRet);
//
// if (sRet.endsWith("/"))
// sRet.remove("/");
return sRet;
}
QString UBCFFAdaptor::UBToCFFConverter::getFileNameFromPath(const QString sPath)
{
QString sRet;
QStringList sl = sPath.split("/",QString::SkipEmptyParts);
if (0 < sl.count())
{
QString name = sl.at(sl.count()-1);
QString extention = getExtentionFromFileName(name);
if (feWgt == extention)
{
name.remove("{");
name.remove("}");
}
name.remove(name.length()-extention.length(), extention.length());
name += convertExtention(extention);
sRet = name;
}
return sRet;
}
QString UBCFFAdaptor::UBToCFFConverter::getExtentionFromFileName(const QString &filename)
{
QStringList sl = filename.split("/",QString::SkipEmptyParts);
if (0 < sl.count())
{
QString name = sl.at(sl.count()-1);
QStringList tl = name.split(".");
return tl.at(tl.count()-1);
}
return QString();
}
QString UBCFFAdaptor::UBToCFFConverter::convertExtention(const QString &ext)
{
QString sRet;
if (feSvg == ext)
sRet = fePng;
else
if (feWgt == ext)
sRet = fePng;
else
sRet = ext;
return sRet;
}
QString UBCFFAdaptor::UBToCFFConverter::getElementTypeFromUBZ(const QDomElement &element)
{
QString sRet;
if (tUBZForeignObject == element.tagName())
{
QString sPath;
if (element.hasAttribute(aUBZType))
{
if (avUBZText == element.attribute(aUBZType))
sRet = tIWBTextArea;
else
sRet = element.attribute(aUBZType);
}
else
{
if (element.hasAttribute(aSrc))
sPath = element.attribute(aSrc);
else
if (element.hasAttribute(aUBZHref))
sPath = element.attribute(aUBZHref);
QStringList tsl = sPath.split(".", QString::SkipEmptyParts);
if (0 < tsl.count())
{
QString elementType = tsl.at(tsl.count()-1);
if (iwbElementImage.contains(elementType))
sRet = tIWBImage;
else
if (iwbElementAudio.contains(elementType))
sRet = tIWBAudio;
else
if (iwbElementVideo.contains(elementType))
sRet = tIWBVideo;
}
}
}
else
sRet = element.tagName();
return sRet;
}
int UBCFFAdaptor::UBToCFFConverter::getElementLayer(const QDomElement &element)
{
int iRetLayer = 0;
if (element.hasAttribute(aZLayer))
iRetLayer = (int)element.attribute(aZLayer).toDouble();
else
iRetLayer = DEFAULT_LAYER;
return iRetLayer;
}
bool UBCFFAdaptor::UBToCFFConverter::itIsSupportedFormat(const QString &format) const
{
bool bRet;
QStringList tsl = format.split(".", QString::SkipEmptyParts);
if (0 < tsl.count())
bRet = cffSupportedFileFormats.contains(tsl.at(tsl.count()-1).toLower());
else
bRet = false;
return bRet;
}
bool UBCFFAdaptor::UBToCFFConverter::itIsFormatToConvert(const QString &format) const
{
foreach (QString f, ubzFormatsToConvert.split(","))
{
if (format == f)
return true;
}
return false;
}
bool UBCFFAdaptor::UBToCFFConverter::itIsSVGElementAttribute(const QString ItemType, const QString &AttrName)
{
QString allowedElementAttributes = iwbSVGItemsAttributes[ItemType];
allowedElementAttributes.remove("/t");
allowedElementAttributes.remove(" ");
foreach(QString attr, allowedElementAttributes.split(","))
{
if (AttrName == attr.trimmed())
return true;
}
return false;
}
bool UBCFFAdaptor::UBToCFFConverter::itIsIWBAttribute(const QString &attribute) const
{
foreach (QString attr, iwbElementAttributes.split(","))
{
if (attribute == attr.trimmed())
return true;
}
return false;
}
bool UBCFFAdaptor::UBToCFFConverter::itIsUBZAttributeToConvert(const QString &attribute) const
{
foreach (QString attr, ubzElementAttributesToConvert.split(","))
{
if (attribute == attr.trimmed())
return true;
}
return false;
}
bool UBCFFAdaptor::UBToCFFConverter::ibwAddLine(int x1, int y1, int x2, int y2, QString color, int width, bool isBackground)
{
bool bRet = true;
QDomDocument doc;
QDomElement svgBackgroundCrossPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":line");
QDomElement iwbBackgroundCrossPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
QString sUUID = QUuid::createUuid().toString();
svgBackgroundCrossPart.setTagName(tIWBLine);
svgBackgroundCrossPart.setAttribute(aX+"1", x1);
svgBackgroundCrossPart.setAttribute(aY+"1", y1);
svgBackgroundCrossPart.setAttribute(aX+"2", x2);
svgBackgroundCrossPart.setAttribute(aY+"2", y2);
svgBackgroundCrossPart.setAttribute(aStroke, color);
svgBackgroundCrossPart.setAttribute(aStrokeWidth, width);
svgBackgroundCrossPart.setAttribute(aID, sUUID);
if (isBackground)
{
iwbBackgroundCrossPart.setAttribute(aRef, sUUID);
iwbBackgroundCrossPart.setAttribute(aLocked, avTrue);
addIWBElementToResultModel(iwbBackgroundCrossPart);
}
addSVGElementToResultModel(svgBackgroundCrossPart, mSvgElements, DEFAULT_BACKGROUND_CROSS_LAYER);
if (!bRet)
{
qDebug() << "|error at creating crosses on background";
errorStr = "CreatingCrossedBackgroundParsingError.";
}
return bRet;
}
QTransform UBCFFAdaptor::UBToCFFConverter::getTransformFromUBZ(const QDomElement &ubzElement)
{
QTransform trRet;
QStringList transformParameters;
QString ubzTransform = ubzElement.attribute(aTransform);
ubzTransform.remove("matrix");
ubzTransform.remove("(");
ubzTransform.remove(")");
transformParameters = ubzTransform.split(",", QString::SkipEmptyParts);
if (6 <= transformParameters.count())
{
QTransform *tr = NULL;
tr = new QTransform(transformParameters.at(0).toDouble(),
transformParameters.at(1).toDouble(),
transformParameters.at(2).toDouble(),
transformParameters.at(3).toDouble(),
transformParameters.at(4).toDouble(),
transformParameters.at(5).toDouble());
trRet = *tr;
delete tr;
}
if (6 <= transformParameters.count())
{
QTransform *tr = NULL;
tr = new QTransform(transformParameters.at(0).toDouble(),
transformParameters.at(1).toDouble(),
transformParameters.at(2).toDouble(),
transformParameters.at(3).toDouble(),
transformParameters.at(4).toDouble(),
transformParameters.at(5).toDouble());
trRet = *tr;
delete tr;
}
return trRet;
}
qreal UBCFFAdaptor::UBToCFFConverter::getAngleFromTransform(const QTransform &tr)
{
qreal angle = -(atan(tr.m21()/tr.m11())*180/PI);
if (tr.m21() > 0 && tr.m11() < 0)
angle += 180;
else
if (tr.m21() < 0 && tr.m11() < 0)
angle += 180;
return angle;
}
void UBCFFAdaptor::UBToCFFConverter::setGeometryFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement)
{
setCoordinatesFromUBZ(ubzElement,iwbElement);
}
void UBCFFAdaptor::UBToCFFConverter::setCoordinatesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement)
{
QTransform tr;
if (QString() != ubzElement.attribute(aTransform))
tr = getTransformFromUBZ(ubzElement);
qreal x = ubzElement.attribute(aX).toDouble();
qreal y = ubzElement.attribute(aY).toDouble();
qreal height = ubzElement.attribute(aHeight).toDouble();
qreal width = ubzElement.attribute(aWidth).toDouble();
qreal alpha = getAngleFromTransform(tr);
QRectF itemRect;
QGraphicsRectItem item;
item.setRect(0,0, width, height);
item.setTransform(tr);
item.setRotation(-alpha);
QMatrix sceneMatrix = item.sceneMatrix();
iwbElement.setAttribute(aX, x);
iwbElement.setAttribute(aY, y);
iwbElement.setAttribute(aHeight, height*sceneMatrix.m22());
iwbElement.setAttribute(aWidth, width*sceneMatrix.m11());
iwbElement.setAttribute(aTransform, QString("rotate(%1) translate(%2,%3)").arg(alpha)
.arg(sceneMatrix.dx())
.arg(sceneMatrix.dy()));
}
bool UBCFFAdaptor::UBToCFFConverter::setContentFromUBZ(const QDomElement &ubzElement, QDomElement &svgElement)
{
bool bRet = true;
QString srcPath;
if (tUBZForeignObject != ubzElement.tagName())
srcPath = ubzElement.attribute(aUBZHref);
else
srcPath = ubzElement.attribute(aSrc);
QString sSrcContentFolder = getSrcContentFolderName(srcPath);
QString sSrcFileName = sourcePath + "/" + srcPath ;
QString fileExtention = getExtentionFromFileName(sSrcFileName);
QString sDstContentFolder = getDstContentFolderName(ubzElement.tagName());
QString sDstFileName(QString(QUuid::createUuid().toString()+"."+convertExtention(fileExtention)));
if (itIsSupportedFormat(fileExtention)) // format is supported and we can copy src. files without changing.
{
sSrcFileName = sourcePath + "/" + sSrcContentFolder + "/" + getFileNameFromPath(srcPath); // some elements must be exported as images, so we take hes existing thumbnails.
QFile srcFile;
srcFile.setFileName(sSrcFileName);
QDir dstDocFolder(destinationPath);
if (!dstDocFolder.exists(sDstContentFolder))
bRet &= dstDocFolder.mkdir(sDstContentFolder);
if (bRet)
{
QString dstFilePath = destinationPath+"/"+sDstContentFolder+"/"+sDstFileName;
bRet &= srcFile.copy(dstFilePath);
}
if (bRet)
{
svgElement.setAttribute(aSVGHref, sDstContentFolder+"/"+sDstFileName);
// NOT by standard! Enable it later!
// validator http://validator.imsglobal.org/iwb/index.jsp?validate=package
//svgElement.setAttribute(aSVGRequiredExtension, svgRequiredExtensionPrefix+convertExtention(fileExtention));
}
}
else
if (itIsFormatToConvert(fileExtention)) // we cannot copy that source files. We need to create dst. file from src. file without copy.
{
if (feSvg == fileExtention)
{
QDir dstDocFolder(destinationPath);
if (!dstDocFolder.exists(sDstContentFolder))
bRet &= dstDocFolder.mkdir(sDstContentFolder);
if (bRet)
{
if (feSvg == fileExtention) // svg images must be converted to PNG.
{
QString dstFilePath = destinationPath+"/"+sDstContentFolder+"/"+sDstFileName;
bRet &= createPngFromSvg(sSrcFileName, dstFilePath, getTransformFromUBZ(ubzElement));
}
else
bRet = false;
}
if (bRet)
{
svgElement.setAttribute(aSVGHref, sDstContentFolder+"/"+sDstFileName);
// NOT by standard! Enable it later!
// validator http://validator.imsglobal.org/iwb/index.jsp?validate=package
//svgElement.setAttribute(aSVGRequiredExtension, svgRequiredExtensionPrefix+fePng);
}
}
}else
{
addLastExportError(QObject::tr("Element ID = ") + QString("%1 \r\n").arg(ubzElement.attribute(aUBZUuid))
+ QString("Source file = ") + QString("%1 \r\n").arg(ubzElement.attribute(aUBZSource))
+ QObject::tr("Content is not supported in destination format."));
bRet = false;
}
if (!bRet)
{
qDebug() << "format is not supported by CFF";
}
return bRet;
}
void UBCFFAdaptor::UBToCFFConverter::setCFFTextFromHTMLTextNode(const QDomElement htmlTextNode, QDomElement &iwbElement)
{
QDomDocument textDoc;
QDomElement textParentElement = iwbElement;
QString textString;
QDomNode htmlPNode = htmlTextNode.firstChild();
bool bTbreak = false;
// reads HTML text strings - each string placed in separate <p> section
while(!htmlPNode.isNull())
{
// add <tbreak> for split strings
if (bTbreak)
{
bTbreak = false;
QDomElement tbreakNode = textDoc.createElementNS(svgIWBNS, svgIWBNSPrefix+":"+tIWBTbreak);
textParentElement.appendChild(tbreakNode.cloneNode(true));
}
QDomNode spanNode = htmlPNode.firstChild();
while (!spanNode.isNull())
{
if (spanNode.isText())
{
QDomText nodeText = textDoc.createTextNode(spanNode.nodeValue());
textParentElement.appendChild(nodeText.cloneNode(true));
}
else
if (spanNode.isElement())
{
QDomElement pElementIwb;
QDomElement spanElement = textDoc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBTspan);
setCommonAttributesFromUBZ(htmlPNode.toElement(), pElementIwb, spanElement);
if (spanNode.hasAttributes())
{
int attrCount = spanNode.attributes().count();
if (0 < attrCount)
{
for (int i = 0; i < attrCount; i++)
{
// html attributes like: style="font-size:40pt; color:"red";".
QStringList cffAttributes = spanNode.attributes().item(i).nodeValue().split(";", QString::SkipEmptyParts);
{
for (int i = 0; i < cffAttributes.count(); i++)
{
QString attr = cffAttributes.at(i).trimmed();
QStringList AttrVal = attr.split(":", QString::SkipEmptyParts);
if(1 < AttrVal.count())
{
QString sAttr = ubzAttrNameToCFFAttrName(AttrVal.at(0));
if (itIsSVGElementAttribute(spanElement.tagName(), sAttr))
spanElement.setAttribute(sAttr, ubzAttrValueToCFFAttrName(AttrVal.at(1)));
}
}
}
}
}
}
QDomText nodeText = textDoc.createTextNode(spanNode.firstChild().nodeValue());
spanElement.appendChild(nodeText);
textParentElement.appendChild(spanElement.cloneNode(true));
}
spanNode = spanNode.nextSibling();
}
bTbreak = true;
htmlPNode = htmlPNode.nextSibling();
}
}
QString UBCFFAdaptor::UBToCFFConverter::ubzAttrNameToCFFAttrName(QString cffAttrName)
{
QString sRet = cffAttrName;
if (QString("color") == cffAttrName)
sRet = QString("fill");
if (QString("align") == cffAttrName)
sRet = QString("text-align");
return sRet;
}
QString UBCFFAdaptor::UBToCFFConverter::ubzAttrValueToCFFAttrName(QString cffValue)
{
QString sRet = cffValue;
if (QString("text") == cffValue)
sRet = QString("normal");
return sRet;
}
bool UBCFFAdaptor::UBToCFFConverter::setCFFAttribute(const QString &attributeName, const QString &attributeValue, const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement)
{
bool bRet = true;
bool bNeedsIWBSection = false;
if (itIsIWBAttribute(attributeName))
{
if (!((aBackground == attributeName) && (avFalse == attributeValue)))
{
iwbElement.setAttribute(attributeName, attributeValue);
bNeedsIWBSection = true;
}
}
else
if (itIsUBZAttributeToConvert(attributeName))
{
if (aTransform == attributeName)
{
setGeometryFromUBZ(ubzElement, svgElement);
}
else
if (attributeName.contains(aUBZUuid))
{
QString parentId = ubzElement.attribute(aUBZParent);
QString id;
if (!parentId.isEmpty())
id = "{" + parentId + "}" + "{" + ubzElement.attribute(aUBZUuid)+"}";
else
id = "{" + ubzElement.attribute(aUBZUuid)+"}";
svgElement.setAttribute(aID, id);
}
else
if (attributeName.contains(aUBZHref)||attributeName.contains(aSrc))
{
bRet &= setContentFromUBZ(ubzElement, svgElement);
bNeedsIWBSection = bRet||bNeedsIWBSection;
}
}
else
if (itIsSVGElementAttribute(svgElement.tagName(),attributeName))
{
svgElement.setAttribute(attributeName, attributeValue);
}
if (bNeedsIWBSection)
{
if (0 < iwbElement.attributes().count())
{
QStringList tl = ubzElement.attribute(aSVGHref).split("/");
QString id = tl.at(tl.count()-1);
// if element already have an ID, we use it. Else we create new id for element.
if (QString() == id)
id = QUuid::createUuid().toString();
svgElement.setAttribute(aID, id);
iwbElement.setAttribute(aRef, id);
}
}
return bRet;
}
bool UBCFFAdaptor::UBToCFFConverter::setCommonAttributesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement)
{
bool bRet = true;
for (int i = 0; i < ubzElement.attributes().count(); i++)
{
QDomNode attribute = ubzElement.attributes().item(i);
QString attributeName = ubzAttrNameToCFFAttrName(attribute.nodeName().remove("ub:"));
bRet &= setCFFAttribute(attributeName, ubzAttrValueToCFFAttrName(attribute.nodeValue()), ubzElement, iwbElement, svgElement);
if (!bRet) break;
}
return bRet;
}
void UBCFFAdaptor::UBToCFFConverter::setViewBox(QRect viewbox)
{
mViewbox |= viewbox;
}
QDomNode UBCFFAdaptor::UBToCFFConverter::findTextNode(const QDomNode &node)
{
QDomNode iterNode = node;
while (!iterNode.isNull())
{
if (iterNode.isText())
{
if (!iterNode.isNull())
return iterNode;
}
else
{
if (!iterNode.firstChild().isNull())
{
QDomNode foundNode = findTextNode(iterNode.firstChild());
if (!foundNode.isNull())
if (foundNode.isText())
return foundNode;
}
}
if (!iterNode.nextSibling().isNull())
iterNode = iterNode.nextSibling();
else
break;
}
return iterNode;
}
QDomNode UBCFFAdaptor::UBToCFFConverter::findNodeByTagName(const QDomNode &node, QString tagName)
{
QDomNode iterNode = node;
while (!iterNode.isNull())
{
QString t = iterNode.toElement().tagName();
if (tagName == t)
return iterNode;
else
{
if (!iterNode.firstChildElement().isNull())
{
QDomNode foundNode = findNodeByTagName(iterNode.firstChildElement(), tagName);
if (!foundNode.isNull()){
if (foundNode.isElement())
{
if (tagName == foundNode.toElement().tagName())
return foundNode;
}
else
break;
}
}
}
if (!iterNode.nextSibling().isNull())
iterNode = iterNode.nextSibling();
else
break;
}
return QDomNode();
}
bool UBCFFAdaptor::UBToCFFConverter::createBackground(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "|creating element background";
QDomDocument doc;
//QDomElement svgBackgroundElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tUBZImage);
QDomElement svgBackgroundElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBRect);
QDomElement iwbBackgroundElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
QRect bckRect(mViewbox);
if (0 <= mViewbox.topLeft().x())
bckRect.topLeft().setX(0);
if (0 <= mViewbox.topLeft().y())
bckRect.topLeft().setY(0);
if (QRect() != bckRect)
{
QString sElementID = QUuid::createUuid().toString();
bool darkBackground = (avTrue == element.attribute(aDarkBackground));
svgBackgroundElementPart.setAttribute(aFill, darkBackground ? "black" : "white");
svgBackgroundElementPart.setAttribute(aID, sElementID);
svgBackgroundElementPart.setAttribute(aX, bckRect.x());
svgBackgroundElementPart.setAttribute(aY, bckRect.y());
svgBackgroundElementPart.setAttribute(aHeight, bckRect.height());
svgBackgroundElementPart.setAttribute(aWidth, bckRect.width());
//svgBackgroundElementPart.setAttribute(aSVGHref, backgroundImagePath);
iwbBackgroundElementPart.setAttribute(aRef, sElementID);
iwbBackgroundElementPart.setAttribute(aBackground, avTrue);
//iwbBackgroundElementPart.setAttribute(aLocked, avTrue);
addSVGElementToResultModel(svgBackgroundElementPart, dstSvgList, DEFAULT_BACKGROUND_LAYER);
addIWBElementToResultModel(iwbBackgroundElementPart);
return true;
}
else
{
qDebug() << "|error at creating element background";
errorStr = "CreatingElementBackgroundParsingError.";
return false;
}
}
QString UBCFFAdaptor::UBToCFFConverter::createBackgroundImage(const QDomElement &element, QSize size)
{
QString sRet;
QString sDstFileName(fIWBBackground);
bool bDirExists = true;
QDir dstDocFolder(destinationPath);
if (!dstDocFolder.exists(cfImages))
bDirExists &= dstDocFolder.mkdir(cfImages);
QString dstFilePath;
if (bDirExists)
dstFilePath = destinationPath+"/"+cfImages+"/"+sDstFileName;
if (!QFile().exists(dstFilePath))
{
QRect rect(0,0, size.width(), size.height());
QImage *bckImage = new QImage(size, QImage::Format_RGB888);
QPainter *painter = new QPainter(bckImage);
bool darkBackground = (avTrue == element.attribute(aDarkBackground));
QColor bCrossColor;
bCrossColor = darkBackground?QColor(Qt::white):QColor(Qt::blue);
int penAlpha = (int)(255/2); // default Sankore value for transform.m11 < 1
bCrossColor.setAlpha(penAlpha);
painter->setPen(bCrossColor);
painter->setBrush(darkBackground?QColor(Qt::black):QColor(Qt::white));
painter->drawRect(rect);
if (avTrue == element.attribute(aCrossedBackground))
{
qreal firstY = ((int) (rect.y () / iCrossSize)) * iCrossSize;
for (qreal yPos = firstY; yPos <= rect.y () + rect.height (); yPos += iCrossSize)
{
painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos);
}
qreal firstX = ((int) (rect.x () / iCrossSize)) * iCrossSize;
for (qreal xPos = firstX; xPos <= rect.x () + rect.width (); xPos += iCrossSize)
{
painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ());
}
}
painter->end();
painter->save();
if (QString() != dstFilePath)
if (bckImage->save(dstFilePath))
sRet = cfImages+"/"+sDstFileName;
delete bckImage;
delete painter;
}
else
sRet = cfImages+"/"+sDstFileName;
return sRet;
}
bool UBCFFAdaptor::UBToCFFConverter::createPngFromSvg(QString &svgPath, QString &dstPath, QTransform transformation, QSize size)
{
if (QFile().exists(svgPath))
{
QImage i(svgPath);
QSize iSize = (QSize() == size)?QSize(i.size().width()*transformation.m11(), i.size().height()*transformation.m22()):size;
QImage image(iSize, QImage::Format_ARGB32_Premultiplied);
image.fill(0);
QPainter imagePainter(&image);
QSvgRenderer renderer(svgPath);
renderer.render(&imagePainter);
return image.save(dstPath);
}
else
return false;
}
bool UBCFFAdaptor::UBToCFFConverter::parseSVGGGroup(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "|parsing g section";
QDomElement nextElement = element.firstChildElement();
if (nextElement.isNull()) {
qDebug() << "Empty g element";
errorStr = "EmptyGSection";
return false;
}
QMultiMap<int, QDomElement> svgElements;
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBG);
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
// Elements can know about its layer, so it must add result QDomElements to ordrered list.
while (!nextElement.isNull()) {
QString tagName = nextElement.tagName();
if (tagName == tUBZLine) parseUBZLine(nextElement, svgElements);
else if (tagName == tUBZPolygon) parseUBZPolygon(nextElement, svgElements);
else if (tagName == tUBZPolyline) parseUBZPolyline(nextElement, svgElements);
nextElement = nextElement.nextSiblingElement();
}
QList<int> layers;
QMapIterator<int, QDomElement> nextSVGElement(svgElements);
while (nextSVGElement.hasNext())
layers << nextSVGElement.next().key();
qSort(layers);
int layer = layers.at(0);
nextSVGElement.toFront();
while (nextSVGElement.hasNext())
svgElementPart.appendChild(nextSVGElement.next().value());
addSVGElementToResultModel(svgElementPart, dstSvgList, layer);
return true;
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZImage(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "|parsing image";
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
addIWBElementToResultModel(iwbElementPart);
return true;
}
else
{
qDebug() << "|error at image parsing";
errorStr = "ImageParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZVideo(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "|parsing video";
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
QDomElement svgSwitchSection = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBSwitch);
svgSwitchSection.appendChild(svgElementPart);
// if viewer cannot open that content - it must use that:
QDomElement svgText = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBTextArea);
svgText.setAttribute(aX, svgElementPart.attribute(aX));
svgText.setAttribute(aY, svgElementPart.attribute(aY));
svgText.setAttribute(aWidth, svgElementPart.attribute(aWidth));
svgText.setAttribute(aHeight, svgElementPart.attribute(aHeight));
svgText.setAttribute(aTransform, svgElementPart.attribute(aTransform));
QDomText text = doc.createTextNode("Cannot Open Content");
svgText.appendChild(text);
svgSwitchSection.appendChild(svgText);
addSVGElementToResultModel(svgSwitchSection, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
addIWBElementToResultModel(iwbElementPart);
return true;
}
else
{
qDebug() << "|error at video parsing";
errorStr = "VideoParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZAudio(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "|parsing audio";
// audio file must be linked to cff item excluding video.
// to do:
// 1 add image for audio element.
// 2 set id for this element
// 3 add <svg:a> section with xlink:href to audio file
// 4 add shild to a section with id of the image
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
//we must create image-containers for audio files
int audioImageDimention = qMin(svgElementPart.attribute(aWidth).toInt(), svgElementPart.attribute(aHeight).toInt());
QString srcAudioImageFile(sAudioElementImage);
QString elementId = QString(QUuid::createUuid().toString());
QString sDstAudioImageFileName = elementId+"."+fePng;
QString dstAudioImageFilePath = destinationPath+"/"+cfImages+"/"+sDstAudioImageFileName;
QString dstAudioImageRelativePath = cfImages+"/"+sDstAudioImageFileName;
QFile srcFile(srcAudioImageFile);
//creating folder for audioImage
QDir dstDocFolder(destinationPath);
bool bRes = true;
if (!dstDocFolder.exists(cfImages))
bRes &= dstDocFolder.mkdir(cfImages);
// CFF cannot show SVG images, so we need to convert it to png.
if (bRes && createPngFromSvg(srcAudioImageFile, dstAudioImageFilePath, getTransformFromUBZ(element), QSize(audioImageDimention, audioImageDimention)))
{
// switch section disabled because of imcompatibility with validator http://validator.imsglobal.org/iwb/index.jsp?validate=package
// QDomElement svgSwitchSection = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBSwitch);
// first we place content
QDomElement svgASection = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBA);
svgASection.setAttribute(aSVGHref, svgElementPart.attribute(aSVGHref));
svgElementPart.setTagName(tIWBImage);
svgElementPart.setAttribute(aSVGHref, dstAudioImageRelativePath);
svgElementPart.setAttribute(aHeight, audioImageDimention);
svgElementPart.setAttribute(aWidth, audioImageDimention);
svgASection.appendChild(svgElementPart);
// switch section disabled because of imcompatibility with validator http://validator.imsglobal.org/iwb/index.jsp?validate=package
// svgSwitchSection.appendChild(svgASection);
// if viewer cannot open that content - it must use that:
QDomElement svgText = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + tIWBTextArea);
svgText.setAttribute(aX, svgElementPart.attribute(aX));
svgText.setAttribute(aY, svgElementPart.attribute(aY));
svgText.setAttribute(aWidth, svgElementPart.attribute(aWidth));
svgText.setAttribute(aHeight, svgElementPart.attribute(aHeight));
svgText.setAttribute(aTransform, svgElementPart.attribute(aTransform));
QDomText text = doc.createTextNode("Cannot Open Content");
svgText.appendChild(text);
// switch section disabled because of imcompatibility with validator http://validator.imsglobal.org/iwb/index.jsp?validate=package
// svgSwitchSection.appendChild(svgText);
// switch section disabled because of imcompatibility with validator http://validator.imsglobal.org/iwb/index.jsp?validate=package
addSVGElementToResultModel(svgASection/*svgSwitchSection*/, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
addIWBElementToResultModel(iwbElementPart);
return true;
}
return false;
}
else
{
qDebug() << "|error at audio parsing";
errorStr = "AudioParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseForeignObject(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
if (element.attribute(aUBZType) == avUBZText) {
return parseUBZText(element, dstSvgList);
}
qDebug() << "|parsing foreign object";
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
addIWBElementToResultModel(iwbElementPart);
return true;
}
else
{
qDebug() << "|error at parsing foreign object";
errorStr = "ForeignObjectParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZText(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "|parsing text";
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (element.hasChildNodes())
{
QDomDocument htmlDoc;
htmlDoc.setContent(findTextNode(element).nodeValue());
QDomNode bodyNode = findNodeByTagName(htmlDoc.firstChildElement(), "body");
setCFFTextFromHTMLTextNode(bodyNode.toElement(), svgElementPart);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
QString commonParams;
for (int i = 0; i < bodyNode.attributes().count(); i++)
{
commonParams += " " + bodyNode.attributes().item(i).nodeValue();
}
commonParams.remove(" ");
commonParams.remove("'");
QStringList commonAttributes = commonParams.split(";", QString::SkipEmptyParts);
for (int i = 0; i < commonAttributes.count(); i++)
{
QStringList AttrVal = commonAttributes.at(i).split(":", QString::SkipEmptyParts);
if (1 < AttrVal.count())
{
QString sAttr = ubzAttrNameToCFFAttrName(AttrVal.at(0));
QString sVal = ubzAttrValueToCFFAttrName(AttrVal.at(1));
setCFFAttribute(sAttr, sVal, element, iwbElementPart, svgElementPart);
}
}
addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
addIWBElementToResultModel(iwbElementPart);
return true;
}
return false;
}
else
{
qDebug() << "|error at text parsing";
errorStr = "TextParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZPolygon(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "||parsing polygon";
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
svgElementPart.setAttribute(aStroke, svgElementPart.attribute(aFill));
addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
{
QString id = svgElementPart.attribute(aUBZUuid);
if (id.isEmpty())
id = QUuid::createUuid().toString();
svgElementPart.setAttribute(aID, id);
iwbElementPart.setAttribute(aRef, id);
addIWBElementToResultModel(iwbElementPart);
}
return true;
}
else
{
qDebug() << "||error at parsing polygon";
errorStr = "PolygonParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZPolyline(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "||parsing polyline";
QDomElement resElement;
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
svgElementPart.setAttribute(aStroke, svgElementPart.attribute(aFill));
addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
{
QString id = QUuid::createUuid().toString();
svgElementPart.setAttribute(aID, id);
iwbElementPart.setAttribute(aRef, id);
addIWBElementToResultModel(iwbElementPart);
}
return true;
}
else
{
qDebug() << "||error at parsing polygon";
errorStr = "PolylineParsingError";
return false;
}
}
bool UBCFFAdaptor::UBToCFFConverter::parseUBZLine(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList)
{
qDebug() << "||parsing line";
QDomElement resElement;
QDomDocument doc;
QDomElement svgElementPart = doc.createElementNS(svgIWBNS,svgIWBNSPrefix + ":" + getElementTypeFromUBZ(element));
QDomElement iwbElementPart = doc.createElementNS(iwbNS,iwbNsPrefix + ":" + tElement);
if (setCommonAttributesFromUBZ(element, iwbElementPart, svgElementPart))
{
svgElementPart.setAttribute(aStroke, svgElementPart.attribute(aFill));
addSVGElementToResultModel(svgElementPart, dstSvgList, getElementLayer(element));
if (0 < iwbElementPart.attributes().count())
{
QString id = QUuid::createUuid().toString();
svgElementPart.setAttribute(aID, id);
iwbElementPart.setAttribute(aRef, id);
addIWBElementToResultModel(iwbElementPart);
}
}
else
{
qDebug() << "||error at parsing polygon";
errorStr = "LineParsingError";
return false;
}
return true;
}
void UBCFFAdaptor::UBToCFFConverter::addSVGElementToResultModel(const QDomElement &element, QMultiMap<int, QDomElement> &dstList, int layer)
{
int elementLayer = (DEFAULT_LAYER == layer) ? DEFAULT_LAYER : layer;
dstList.setInsertInOrder(true);
QDomElement rootElement = element.cloneNode(true).toElement();
mDocumentToWrite->firstChildElement().appendChild(rootElement);
dstList.insert(elementLayer, rootElement);
}
void UBCFFAdaptor::UBToCFFConverter::addIWBElementToResultModel(const QDomElement &element)
{
QDomElement rootElement = element.cloneNode(true).toElement();
mDocumentToWrite->firstChildElement().appendChild(rootElement);
mExtendedElements.append(rootElement);
}
UBCFFAdaptor::UBToCFFConverter::~UBToCFFConverter()
{
if (mDataModel)
delete mDataModel;
if (mIWBContentWriter)
delete mIWBContentWriter;
if (mDocumentToWrite)
delete mDocumentToWrite;
}
bool UBCFFAdaptor::UBToCFFConverter::isValid() const
{
bool result = QFileInfo(sourcePath).exists()
&& QFileInfo(sourcePath).isDir()
&& errorStr == noErrorMsg;
if (!result) {
qDebug() << "specified data is not valid";
errorStr = "ValidateDataError";
}
return result;
}
void UBCFFAdaptor::UBToCFFConverter::fillNamespaces()
{
mIWBContentWriter->writeDefaultNamespace(svgUBZNS);
mIWBContentWriter->writeNamespace(iwbNS, iwbNsPrefix);
mIWBContentWriter->writeNamespace(svgIWBNS, svgIWBNSPrefix);
mIWBContentWriter->writeNamespace(xlinkNS, xlinkNSPrefix);
}
QString UBCFFAdaptor::UBToCFFConverter::digitFileFormat(int digit) const
{
return QString("%1").arg(digit, 3, 10, QLatin1Char('0'));
}
QString UBCFFAdaptor::UBToCFFConverter::contentIWBFileName() const
{
return destinationPath + "/" + fIWBContent;
}
//setting SVG dimenitons
QSize UBCFFAdaptor::UBToCFFConverter::getSVGDimentions(const QString &element)
{
QStringList dimList;
dimList = element.split(dimensionsDelimiter1, QString::KeepEmptyParts);
if (dimList.count() != 2) // row unlike 0x0
return QSize();
bool ok;
int width = dimList.takeFirst().toInt(&ok);
if (!ok || !width)
return QSize();
int height = dimList.takeFirst().toInt(&ok);
if (!ok || !height)
return QSize();
return QSize(width, height);
}
//Setting viewbox rectangle
QRect UBCFFAdaptor::UBToCFFConverter::getViewboxRect(const QString &element) const
{
QStringList dimList;
dimList = element.split(dimensionsDelimiter2, QString::KeepEmptyParts);
if (dimList.count() != 4) // row unlike 0 0 0 0
return QRect();
bool ok = false;
int x = dimList.takeFirst().toInt(&ok);
if (!ok || !x)
return QRect();
int y = dimList.takeFirst().toInt(&ok);
if (!ok || !y)
return QRect();
int width = dimList.takeFirst().toInt(&ok);
if (!ok || !width)
return QRect();
int height = dimList.takeFirst().toInt(&ok);
if (!ok || !height)
return QRect();
return QRect(x, y, width, height);
}
QString UBCFFAdaptor::UBToCFFConverter::rectToIWBAttr(const QRect &rect) const
{
if (rect.isNull()) return QString();
return QString("%1 %2 %3 %4").arg(rect.topLeft().x())
.arg(rect.topLeft().y())
.arg(rect.width())
.arg(rect.height());
}
UBCFFAdaptor::UBToUBZConverter::UBToUBZConverter()
{
}
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBCFFADAPTOR_H
#define UBCFFADAPTOR_H
#include "UBCFFAdaptor_global.h"
#include <QtCore>
class QTransform;
class QDomDocument;
class QDomElement;
class QDomNode;
class QuaZipFile;
class UBCFFADAPTORSHARED_EXPORT UBCFFAdaptor {
class UBToCFFConverter;
public:
UBCFFAdaptor();
~UBCFFAdaptor();
bool convertUBZToIWB(const QString &from, const QString &to);
bool deleteDir(const QString& pDirPath) const;
QList<QString> getConversionMessages();
private:
QString uncompressZip(const QString &zipFile);
bool compressZip(const QString &source, const QString &destination);
bool compressDir(const QString &dirName, const QString &parentDir, QuaZipFile *outZip);
bool compressFile(const QString &fileName, const QString &parentDir, QuaZipFile *outZip);
QString createNewTmpDir();
bool freeDir(const QString &dir);
void freeTmpDirs();
private:
QStringList tmpDirs;
QList<QString> mConversionMessages;
private:
class UBToCFFConverter {
static const int DEFAULT_LAYER = -100000;
public:
UBToCFFConverter(const QString &source, const QString &destination);
~UBToCFFConverter();
bool isValid() const;
QString lastErrStr() const {return errorStr;}
bool parse();
QList<QString> getMessages() {return mExportErrorList;}
private:
void addLastExportError(QString error) {mExportErrorList.append(error);}
void fillNamespaces();
bool parseMetadata();
bool parseContent();
QDomElement parsePageset(const QStringList &pageFileNames);
QDomElement parsePage(const QString &pageFileName);
QDomElement parseSvgPageSection(const QDomElement &element);
void writeQDomElementToXML(const QDomNode &node);
bool writeExtendedIwbSection();
QDomElement parseGroupsPageSection(const QDomElement &groupRoot);
bool createBackground(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
QString createBackgroundImage(const QDomElement &element, QSize size);
bool createPngFromSvg(QString &svgPath, QString &dstPath, QTransform transformation, QSize size = QSize());
bool parseSVGGGroup(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZImage(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZVideo(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZAudio(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseForeignObject(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZText(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZPolygon(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZPolyline(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
bool parseUBZLine(const QDomElement &element, QMultiMap<int, QDomElement> &dstSvgList);
void addSVGElementToResultModel(const QDomElement &element, QMultiMap<int, QDomElement> &dstList, int layer = DEFAULT_LAYER);
void addIWBElementToResultModel(const QDomElement &element);
qreal getAngleFromTransform(const QTransform &tr);
QString getDstContentFolderName(const QString &elementType);
QString getSrcContentFolderName(QString href);
QString getFileNameFromPath(QString sPath);
QString getExtentionFromFileName(const QString &filename);
QString convertExtention(const QString &ext);
QString getElementTypeFromUBZ(const QDomElement &element);
int getElementLayer(const QDomElement &element);
bool itIsSupportedFormat(const QString &format) const;
bool itIsFormatToConvert(const QString &format) const;
bool itIsSVGElementAttribute(const QString ItemType, const QString &AttrName);
bool itIsIWBAttribute(const QString &attribute) const;
bool itIsUBZAttributeToConvert(const QString &attribute) const;
bool ibwAddLine(int x1, int y1, int x2, int y2, QString color=QString(), int width=1, bool isBackground=false);
QTransform getTransformFromUBZ(const QDomElement &ubzElement);
void setGeometryFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement);
void setCoordinatesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement);
bool setContentFromUBZ(const QDomElement &ubzElement, QDomElement &svgElement);
void setCFFTextFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement);
void setCFFTextFromHTMLTextNode(const QDomElement htmlTextNode, QDomElement &iwbElement);
QString ubzAttrNameToCFFAttrName(QString cffAttrName);
QString ubzAttrValueToCFFAttrName(QString cffAttrValue);
bool setCFFAttribute(const QString &attributeName, const QString &attributeValue, const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement);
bool setCommonAttributesFromUBZ(const QDomElement &ubzElement, QDomElement &iwbElement, QDomElement &svgElement);
void setViewBox(QRect viewbox);
QDomNode findTextNode(const QDomNode &node);
QDomNode findNodeByTagName(const QDomNode &node, QString tagName);
QSize getSVGDimentions(const QString &element);
inline QRect getViewboxRect(const QString &element) const;
inline QString rectToIWBAttr(const QRect &rect) const;
inline QString digitFileFormat(int num) const;
inline bool strToBool(const QString &in) const {return in == "true";}
QString contentIWBFileName() const;
private:
QList<QString> mExportErrorList;
QMap<QString, QString> iwbSVGItemsAttributes;
QDomDocument *mDataModel; //model for reading indata
QXmlStreamWriter *mIWBContentWriter; //stream to write outdata
QSize mSVGSize; //svg page size
QRect mViewbox; //Main viewbox parameter for CFF
QString sourcePath; // dir with unpacked source data (ubz)
QString destinationPath; //dir with unpacked destination data (iwb)
QDomDocument *mDocumentToWrite; //document for saved QDomElements from mSvgElements and mExtendedElements
QMultiMap<int, QDomElement> mSvgElements; //Saving svg elements to have a sorted by z order list of elements to write;
QList<QDomElement> mExtendedElements; //Saving extended options of elements to be able to add them to the end of result iwb document;
mutable QString errorStr; // last error string message
public:
operator bool() const {return isValid();}
};
class UBToUBZConverter {
public:
UBToUBZConverter();
};
};
#endif // UBCFFADAPTOR_H
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBCFFADAPTOR_GLOBAL_H
#define UBCFFADAPTOR_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(UBCFFADAPTOR_LIBRARY)
# define UBCFFADAPTORSHARED_EXPORT Q_DECL_EXPORT
#else
# define UBCFFADAPTORSHARED_EXPORT Q_DECL_IMPORT
#endif
#endif // UBCFFADAPTOR_GLOBAL_H
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBCFFCONSTANTS_H
#define UBCFFCONSTANTS_H
#define PI 3.1415926535
const int DEFAULT_BACKGROUND_LAYER = -20000002;
const int DEFAULT_BACKGROUND_CROSS_LAYER = -20000001;
// Constant names. Use only them instead const char* in each function
// Constant fileNames;
const QString fMetadata = "metadata.rdf";
const QString fIWBContent = "content.xml";
const QString fIWBBackground = "background.png";
const QString sAudioElementImage = ":images/soundOn.svg";
// Constant messages;
const QString noErrorMsg = "NoError";
// Tag names
const QString tDescription = "Description";
const QString tIWBRoot = "iwb";
const QString tIWBMeta = "meta";
const QString tUBZSize = "size";
const QString tSvg = "svg";
const QString tIWBPage = "page";
const QString tIWBPageSet = "pageset";
const QString tId = "id";
const QString tElement = "element";
const QString tUBZGroup = "group";
const QString tUBZGroups = "groups";
const QString tUBZG = "g";
const QString tUBZPolygon = "polygon";
const QString tUBZPolyline = "polyline";
const QString tUBZLine = "line";
const QString tUBZAudio = "audio";
const QString tUBZVideo = "video";
const QString tUBZImage = "image";
const QString tUBZForeignObject = "foreignObject";
const QString tUBZTextContent = "itemTextContent";
const QString tIWBA = "a";
const QString tIWBG = "g";
const QString tIWBSwitch = "switch";
const QString tIWBImage = "image";
const QString tIWBVideo = "video";
const QString tIWBAudio = "audio";
const QString tIWBText = "text";
const QString tIWBTextArea = "textarea";
const QString tIWBPolyLine = "polyline";
const QString tIWBPolygon = "polygon";
const QString tIWBFlash = "video";
const QString tIWBRect = "rect";
const QString tIWBLine = "line";
const QString tIWBTbreak = "tbreak";
const QString tIWBTspan = "tspan";
// Attributes names
const QString aIWBVersion = "version";
const QString aOwner = "owner";
const QString aDescription = "description";
const QString aCreator = "creator";
const QString aAbout = "about";
const QString aIWBViewBox = "viewbox";
const QString aUBZViewBox = "viewBox";
const QString aDarkBackground = "dark-background";
const QString aBackground = "background";
const QString aCrossedBackground = "crossed-background";
const QString aUBZType = "type";
const QString aUBZUuid = "uuid";
const QString aUBZParent = "parent";
const QString aFill = "fill"; // IWB attribute contans color to fill
const QString aID = "id"; // ID of any svg element can be placed in to iwb section
const QString aRef = "ref"; // as reference for applying additional attributes
const QString aSVGHref = "xlink:href"; // reference to file
const QString aIWBHref = "ref"; // reference to element ID
const QString aUBZHref = "href";
const QString aUBZSource = "source";
const QString aSrc = "src";
const QString aSVGRequiredExtension = "requiredExtensions";
const QString aX = "x";
const QString aY = "y";
const QString aWidth = "width";
const QString aHeight = "height";
const QString aStroke = "stroke";
const QString aStrokeWidth = "stroke-width";
const QString aPoints = "points";
const QString aZLayer = "z-value";
const QString aLayer = "layer";
const QString aTransform = "transform";
const QString aLocked = "locked";
const QString aIWBName = "name";
const QString aIWBContent = "content";
// Attribute values
const QString avIWBVersionNo = "1.0";
const QString avUBZText = "text";
const QString avFalse = "false";
const QString avTrue = "true";
// Namespaces and prefixes
const QString svgRequiredExtensionPrefix = "http://www.imsglobal.org/iwb/";
const QString dcNS = "http://purl.org/dc/elements/1.1/";
const QString svgUBZNS = "http://www.imsglobal.org/xsd/iwb_v1p0";
const QString svgIWBNS = "http://www.w3.org/2000/svg";
const QString xlinkNS = "http://www.w3.org/1999/xlink";
const QString iwbNS = "http://www.imsglobal.org/xsd/iwb_v1p0";
const QString xsiNS = "http://www.w3.org/2001/XMLSchema-instance";
const QString xsiShemaLocation = "\
http://www.imsglobal.org/xsd/iwb_v1p0 \
http://www.imsglobal.org/profile/iwb/iwbv1p0_v1p0.xsd \
http://www.w3.org/2000/svg http://www.imsglobal.org/profile/iwb/svgsubsetv1p0_v1p0.xsd \
http://www.w3.org/1999/xlink http://www.imsglobal.org/xsd/w3/1999/xlink.xsd";
const QString dcNSPrefix = "dc";
const QString svgIWBNSPrefix = "svg";
const QString xlinkNSPrefix = "xlink";
const QString iwbNsPrefix = "iwb";
const QString xsiPrefix = "xsi";
const QString xsiSchemaLocationPrefix = "schemaLocation";
const QString avOwner = "";
const QString avCreator = "";
const QString avDescription = "";
//constant symbols and words etc
const QString dimensionsDelimiter1 = "x";
const QString dimensionsDelimiter2 = " ";
const QString pageAlias = "page";
const QString pageFileExtentionUBZ = "svg";
//content folder names
const QString cfImages = "images";
const QString cfVideos = "video";
const QString cfAudios = "audio";
const QString cfFlash = "flash";
//known file extentions
const QString feSvg = "svg";
const QString feWgt = "wgt";
const QString fePng = "png";
const int iCrossSize = 32;
const int iCrossWidth = 1;
// Image formats supported by CFF exclude wgt. Wgt is Sankore widget, which is considered as a .png preview.
const QString iwbElementImage(" \
wgt, \
jpeg, \
jpg, \
bmp, \
gif, \
wmf, \
emf, \
png, \
tif, \
tiff \
");
// Video formats supported by CFF
const QString iwbElementVideo(" \
mpg, \
mpeg, \
swf, \
");
// Audio formats supported by CFF
const QString iwbElementAudio(" \
mp3, \
wav \
");
const QString cffSupportedFileFormats(iwbElementImage + iwbElementVideo + iwbElementAudio);
const QString ubzFormatsToConvert("svg");
const QString iwbSVGImageAttributes(" \
id, \
xlink:href, \
x, \
y, \
height, \
width, \
fill-opacity, \
requiredExtentions, \
transform \
");
const QString iwbSVGAudioAttributes(" \
id, \
xlink:href, \
x, \
y, \
height, \
width, \
fill-opacity, \
requiredExtentions, \
transform \
");
const QString iwbSVGVideoAttributes(" \
id, \
xlink:href, \
x, \
y, \
height, \
width, \
fill-opacity, \
requiredExtentions, \
transform \
");
const QString iwbSVGRectAttributes(" \
id, \
x, \
y, \
height, \
width, \
fill, \
fill-opacity, \
stroke, \
stroke-dasharray, \
stroke-linecap, \
stroke-linejoin, \
stroke-opacity, \
stroke-width, \
transform \
");
const QString iwbSVGTextAttributes(" \
id, \
x, \
y, \
fill, \
font-family, \
font-size, \
font-style, \
font-weight, \
font-stretch, \
transform \
");
const QString iwbSVGTextAreaAttributes(" \
id, \
x, \
y, \
height, \
width, \
fill, \
font-family, \
font-size, \
font-style, \
font-weight, \
font-stretch, \
text-align, \
transform \
");
const QString iwbSVGTspanAttributes(" \
id, \
fill, \
font-family, \
font-size, \
font-style, \
font-weight, \
font-stretch, \
text-align, \
");
const QString iwbSVGLineAttributes(" \
id, \
x1, \
y1, \
x2, \
y2, \
stroke, \
stroke-dasharray, \
stroke-width, \
stroke-opacity, \
stroke-linecap, \
transform \
");
const QString iwbSVGPolyLineAttributes(" \
id, \
points, \
stroke, \
stroke-width, \
stroke-dasharray, \
stroke-opacity, \
stroke-linecap, \
transform \
");
const QString iwbSVGPolygonAttributes(" \
id, \
points, \
fill, \
fill-opacity, \
stroke, \
stroke-dasharray, \
stroke-width, \
stroke-linecap, \
stroke-linejoin, \
stroke-opacity, \
stroke-width, \
transform \
");
// 1 to 1 copy to SVG section
const QString iwbElementAttributes(" \
background, \
background-fill, \
background-posture, \
flip, \
freehand, \
highlight, \
highlight-fill, \
list-style-type, \
list-style-type-fill, \
locked, \
replicate, \
revealer, \
stroke-lineshape-start, \
stroke-lineshape-end \
");
// cannot be copied 1 to 1 to SVG section
const QString ubzElementAttributesToConvert(" \
xlink:href, \
src, \
transform, \
uuid \
"
);
// additional attributes. Have references in SVG section.
const QString svgElementAttributes(" \
points, \
fill, \
fill-opacity, \
stroke, \
stroke-dasharray, \
stroke-linecap, \
stroke-opacity, \
stroke-width, \
stroke_linejoin, \
requiredExtensions, \
viewbox, \
x, \
y, \
x1, \
y1, \
x2, \
y2, \
height, \
width, \
font-family, \
font-size, \
font-style, \
font-weight, \
font-stretch, \
text-align \
");
const QString ubzContentFolders("audios,videos,images,widgets");
struct UBItemLayerType
{
enum Enum
{
FixedBackground = -2000, Object = -1000, Graphic = 0, Tool = 1000, Control = 2000
};
};
#endif // UBCFFCONSTANTS_H
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBGLOBALS_H
#define UBGLOBALS_H
#define DELETEPTR(ptr) if(NULL != ptr){ \
delete ptr; \
ptr = NULL; \
}
#ifdef Q_WS_WIN
#define WARNINGS_DISABLE __pragma(warning(push, 0));
#define WARNINGS_ENABLE __pragma(warning(pop));
#ifdef NO_THIRD_PARTY_WARNINGS
// disabling warning level to 0 and save old state
#define THIRD_PARTY_WARNINGS_DISABLE WARNINGS_DISABLE
#else
// just save old state (needs for not empty define)
#define THIRD_PARTY_WARNINGS_DISABLE __pragma(warning(push));
#endif //#ifdef NO_THIRD_PARTY_WARNINGS
// anyway on WIN
#define THIRD_PARTY_WARNINGS_ENABLE WARNINGS_ENABLE
#else //#ifdef Q_WS_WIN
#define WARNINGS_DISABLE _Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\""); \
_Pragma("GCC diagnostic ignored \"-Wunused-variable\""); \
_Pragma("GCC diagnostic ignored \"-Wsign-compare\"");
#define WARNINGS_ENABLE _Pragma("GCC diagnostic pop");
#ifdef NO_THIRD_PARTY_WARNINGS
//disabling some warnings
#define THIRD_PARTY_WARNINGS_DISABLE WARNINGS_DISABLE
#define THIRD_PARTY_WARNINGS_ENABLE WARNINGS_ENABLE
#else
// just save old state (needs for not empty define)
#define THIRD_PARTY_WARNINGS_ENABLE WARNINGS_ENABLE
#endif //#ifdef NO_THIRD_PARTY_WARNINGS
#endif //#ifdef Q_WS_WIN
#endif // UBGLOBALS_H
HEADERS += plugins/cffadaptor/src/UBCFFAdaptor_global.h \
plugins/cffadaptor/src/UBCFFAdaptor.h \
plugins/cffadaptor/src/UBCFFConstants.h \
plugins/cffadaptor/src/UBGlobals.h
SOURCES += plugins/cffadaptor/src/UBCFFAdaptor.cpp
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <QRegExp>
#include <QSvgGenerator>
#include <QSvgRenderer>
#include <QPixmap>
#include <QMap>
#include "core/UBPersistenceManager.h"
#include "document/UBDocumentProxy.h"
#include "domain/UBItem.h"
#include "domain/UBGraphicsPolygonItem.h"
#include "domain/UBGraphicsStroke.h"
#include "domain/UBGraphicsTextItem.h"
#include "domain/UBGraphicsSvgItem.h"
#include "domain/UBGraphicsPixmapItem.h"
#include "domain/UBGraphicsMediaItem.h"
#include "domain/UBGraphicsWidgetItem.h"
#include "domain/UBGraphicsTextItem.h"
#include "domain/UBGraphicsTextItemDelegate.h"
#include "domain/UBGraphicsWidgetItem.h"
#include "domain/UBGraphicsGroupContainerItem.h"
#include "frameworks/UBFileSystemUtils.h"
#include "UBCFFSubsetAdaptor.h"
#include "UBMetadataDcSubsetAdaptor.h"
#include "UBThumbnailAdaptor.h"
#include "UBSvgSubsetAdaptor.h"
#include "core/UBApplication.h"
#include "QFile"
#include "core/memcheck.h"
//#include "qtlogger.h"
//tag names definition. Use them everiwhere!
static QString tElement = "element";
static QString tGroup = "group";
static QString tEllipse = "ellipse";
static QString tIwb = "iwb";
static QString tMeta = "meta";
static QString tPage = "page";
static QString tPageset = "pageset";
static QString tG = "g";
static QString tSwitch = "switch";
static QString tPolygon = "polygon";
static QString tPolyline = "polyline";
static QString tRect = "rect";
static QString tSvg = "svg";
static QString tText = "text";
static QString tTextarea = "textarea";
static QString tTspan = "tspan";
static QString tBreak = "tbreak";
static QString tImage = "image";
static QString tFlash = "flash";
static QString tAudio = "a";
static QString tVideo = "video";
//attribute names definition
static QString aFill = "fill";
static QString aFillopacity = "fill-opacity";
static QString aX = "x";
static QString aY = "y";
static QString aWidth = "width";
static QString aHeight = "height";
static QString aStroke = "stroke";
static QString aStrokewidth = "stroke-width";
static QString aCx = "cx";
static QString aCy = "cy";
static QString aRx = "rx";
static QString aRy = "ry";
static QString aTransform = "transform";
static QString aViewbox = "viewbox";
static QString aFontSize = "font-size";
static QString aFontfamily = "font-family";
static QString aFontstretch = "font-stretch";
static QString aFontstyle = "font-style";
static QString aFontweight = "font-weight";
static QString aTextalign = "text-align";
static QString aPoints = "points";
static QString svgNS = "http://www.w3.org/2000/svg";
static QString iwbNS = "http://www.imsglobal.org/xsd/iwb_v1p0";
static QString aId = "id";
static QString aRef = "ref";
static QString aHref = "href";
static QString aBackground = "background";
static QString aLocked = "locked";
static QString aEditable = "editable";
//attributes part names
static QString apRotate = "rotate";
static QString apTranslate = "translate";
UBCFFSubsetAdaptor::UBCFFSubsetAdaptor()
{}
bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentProxy* pDocument)
{
//TODO
// fill document proxy metadata
// create persistance manager to save data using proxy
// create UBCFFSubsetReader and make it parse cffSourceFolder
QFile file(cffSourceFile);
if (!file.open(QIODevice::ReadOnly))
{
qWarning() << "Cannot open file " << cffSourceFile << " for reading ...";
return false;
}
UBCFFSubsetReader cffReader(pDocument, &file);
bool result = cffReader.parse();
file.close();
return result;
}
UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy, QFile *content)
: mProxy(proxy)
, mGSectionContainer(NULL)
{
int errorLine, errorColumn;
QString errorStr;
if(!mDOMdoc.setContent(content, true, &errorStr, &errorLine, &errorColumn)){
qWarning() << "Error:Parseerroratline" << errorLine << ","
<< "column" << errorColumn << ":" << errorStr;
} else {
qDebug() << "well parsed to DOM";
pwdContent = QFileInfo(content->fileName()).dir().absolutePath();
}
qDebug() << "tmp path is" << pwdContent;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parse()
{
UBMetadataDcSubsetAdaptor::persist(mProxy);
mIndent = "";
if (!getTempFileName() || !createTempFlashPath())
return false;
if (mDOMdoc.isNull())
return false;
bool result = parseDoc();
if (result)
result = mProxy->pageCount() != 0;
if (QFile::exists(mTempFilePath))
QFile::remove(mTempFilePath);
// if (mTmpFlashDir.exists())
// UBFileSystemUtils::deleteDir(mTmpFlashDir.path());
return result;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseGSection(const QDomElement &element)
{
mGSectionContainer = new UBGraphicsGroupContainerItem();
QDomElement currentSvgElement = element.firstChildElement();
while (!currentSvgElement.isNull()) {
parseSvgElement(currentSvgElement);
currentSvgElement = currentSvgElement.nextSiblingElement();
}
if (mGSectionContainer->childItems().count())
{
mCurrentScene->addGroup(mGSectionContainer);
}
else
{
delete mGSectionContainer;
}
mGSectionContainer = NULL;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgSwitchSection(const QDomElement &element)
{
QDomElement currentSvgElement = element.firstChildElement();
while (!currentSvgElement.isNull()) {
if (parseSvgElement(currentSvgElement))
return true;
}
return false;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgRect(const QDomElement &element)
{
qreal x1 = element.attribute(aX).toDouble();
qreal y1 = element.attribute(aY).toDouble();
//rect dimensions
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
QString textFillColor = element.attribute(aFill);
QString textStrokeColor = element.attribute(aStroke);
QString textStrokeWidth = element.attribute(aStrokewidth);
QColor fillColor = !textFillColor.isNull() ? colorFromString(textFillColor) : QColor();
QColor strokeColor = !textStrokeColor.isNull() ? colorFromString(textStrokeColor) : QColor();
int strokeWidth = textStrokeWidth.toInt();
x1 -= strokeWidth/2;
y1 -= strokeWidth/2;
width += strokeWidth;
height += strokeWidth;
//init svg generator with temp file
QSvgGenerator *generator = createSvgGenerator(width, height);
//init painter to paint to svg
QPainter painter;
painter.begin(generator);
//fill rect
if (fillColor.isValid()) {
painter.setBrush(QBrush(fillColor));
painter.fillRect(0, 0, width, height, fillColor);
}
QPen pen;
if (strokeColor.isValid()) {
pen.setColor(strokeColor);
}
if (strokeWidth)
pen.setWidth(strokeWidth);
painter.setPen(pen);
painter.drawRect(0, 0, width, height);
painter.end();
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
svgItem->setUuid(QUuid(uuid));
QTransform transform;
QString textTransform = element.attribute(aTransform);
svgItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, svgItem);
}
repositionSvgItem(svgItem, width, height, x1, y1, transform);
hashSceneItem(element, svgItem);
if (mGSectionContainer)
{
addItemToGSection(svgItem);
}
delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgEllipse(const QDomElement &element)
{
//ellipse horisontal and vertical radius
qreal rx = element.attribute(aRx).toDouble();
qreal ry = element.attribute(aRy).toDouble();
QSvgGenerator *generator = createSvgGenerator(rx * 2, ry * 2);
//fill and stroke color
QColor fillColor = colorFromString(element.attribute(aFill));
QColor strokeColor = colorFromString(element.attribute(aStroke));
int strokeWidth = element.attribute(aStrokewidth).toInt();
//ellipse center coordinates
qreal cx = element.attribute(aCx).toDouble();
qreal cy = element.attribute(aCy).toDouble();
//init painter to paint to svg
QPainter painter;
painter.begin(generator);
QPen pen(strokeColor);
pen.setWidth(strokeWidth);
painter.setPen(pen);
painter.setBrush(QBrush(fillColor));
painter.drawEllipse(0, 0, rx * 2, ry * 2);
painter.end();
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
svgItem->setUuid(QUuid(uuid));
QTransform transform;
QString textTransform = element.attribute(aTransform);
svgItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, svgItem);
}
repositionSvgItem(svgItem, rx * 2, ry * 2, cx - 2*rx, cy+ry, transform);
hashSceneItem(element, svgItem);
if (mGSectionContainer)
{
addItemToGSection(svgItem);
}
delete generator;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPolygon(const QDomElement &element)
{
QString svgPoints = element.attribute(aPoints);
QPolygonF polygon;
if (!svgPoints.isNull()) {
QStringList ts = svgPoints.split(QLatin1Char(' '), QString::SkipEmptyParts);
foreach(const QString sPoint, ts) {
QStringList sCoord = sPoint.split(QLatin1Char(','), QString::SkipEmptyParts);
if (sCoord.size() == 2) {
QPointF point;
point.setX(sCoord.at(0).toFloat());
point.setY(sCoord.at(1).toFloat());
polygon << point;
}
else if (sCoord.size() == 4){
//This is the case on system were the "," is used to seperate decimal
QPointF point;
QString x = sCoord.at(0) + "." + sCoord.at(1);
QString y = sCoord.at(2) + "." + sCoord.at(3);
point.setX(x.toFloat());
point.setY(y.toFloat());
polygon << point;
}
else {
qWarning() << "cannot make sense of a 'point' value" << sCoord;
}
}
}
//bounding rect lef top corner coordinates
qreal x1 = polygon.boundingRect().topLeft().x();
qreal y1 = polygon.boundingRect().topLeft().y();
//bounding rect dimensions
qreal width = polygon.boundingRect().width();
qreal height = polygon.boundingRect().height();
QString strokeColorText = element.attribute(aStroke);
QString fillColorText = element.attribute(aFill);
QString strokeWidthText = element.attribute(aStrokewidth);
QColor strokeColor = !strokeColorText.isEmpty() ? colorFromString(strokeColorText) : QColor();
QColor fillColor = !fillColorText.isEmpty() ? colorFromString(fillColorText) : QColor();
int strokeWidth = strokeWidthText.toDouble();
QPen pen;
pen.setColor(strokeColor);
pen.setWidth(strokeWidth);
QBrush brush;
brush.setColor(fillColor);
brush.setStyle(Qt::SolidPattern);
QUuid itemUuid(element.attribute(aId).right(QUuid().toString().length()));
QUuid itemGroupUuid(element.attribute(aId).left(QUuid().toString().length()-1));
if (!itemUuid.isNull() && (itemGroupUuid!=itemUuid)) // reimported from UBZ
{
UBGraphicsPolygonItem *graphicsPolygon = mCurrentScene->polygonToPolygonItem(polygon);
graphicsPolygon->setBrush(brush);
QTransform transform;
QString textTransform = element.attribute(aTransform);
graphicsPolygon->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, graphicsPolygon);
}
mCurrentScene->addItem(graphicsPolygon);
graphicsPolygon->setUuid(itemUuid);
mRefToUuidMap.insert(element.attribute(aId), itemUuid);
}
else // single CFF
{
QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width());
QPainter painter;
painter.begin(generator); //drawing to svg tmp file
painter.translate(pen.widthF() / 2 - x1, pen.widthF() / 2 - y1);
painter.setBrush(brush);
painter.setPen(pen);
painter.drawPolygon(polygon);
painter.end();
//add resulting svg file to scene
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QTransform transform;
QString textTransform = element.attribute(aTransform);
QUuid uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
svgItem->setUuid(uuid);
svgItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, svgItem);
}
repositionSvgItem(svgItem, width +strokeWidth, height + strokeWidth, x1 - strokeWidth/2 + transform.m31(), y1 + strokeWidth/2 + transform.m32(), transform);
hashSceneItem(element, svgItem);
if (mGSectionContainer)
{
addItemToGSection(svgItem);
}
delete generator;
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPolyline(const QDomElement &element)
{
QString svgPoints = element.attribute(aPoints);
QPolygonF polygon;
if (!svgPoints.isNull()) {
QStringList ts = svgPoints.split(QLatin1Char(' '),
QString::SkipEmptyParts);
foreach(const QString sPoint, ts) {
QStringList sCoord = sPoint.split(QLatin1Char(','), QString::SkipEmptyParts);
if (sCoord.size() == 2) {
QPointF point;
point.setX(sCoord.at(0).toFloat());
point.setY(sCoord.at(1).toFloat());
polygon << point;
}
else if (sCoord.size() == 4){
//This is the case on system were the "," is used to seperate decimal
QPointF point;
QString x = sCoord.at(0) + "." + sCoord.at(1);
QString y = sCoord.at(2) + "." + sCoord.at(3);
point.setX(x.toFloat());
point.setY(y.toFloat());
polygon << point;
}
else {
qWarning() << "cannot make sense of a 'point' value" << sCoord;
}
}
}
//bounding rect lef top corner coordinates
qreal x1 = polygon.boundingRect().topLeft().x();
qreal y1 = polygon.boundingRect().topLeft().y();
//bounding rect dimensions
qreal width = polygon.boundingRect().width();
qreal height = polygon.boundingRect().height();
QString strokeColorText = element.attribute(aStroke);
QString strokeWidthText = element.attribute(aStrokewidth);
QColor strokeColor = !strokeColorText.isEmpty() ? colorFromString(strokeColorText) : QColor();
int strokeWidth = strokeWidthText.toDouble();
width += strokeWidth;
height += strokeWidth;
QPen pen;
pen.setColor(strokeColor);
pen.setWidth(strokeWidth);
QBrush brush;
brush.setColor(strokeColor);
brush.setStyle(Qt::SolidPattern);
QUuid itemUuid(element.attribute(aId).right(QUuid().toString().length()));
QUuid itemGroupUuid(element.attribute(aId).left(QUuid().toString().length()-1));
if (!itemUuid.isNull() && (itemGroupUuid!=itemUuid)) // reimported from UBZ
{
UBGraphicsPolygonItem *graphicsPolygon = new UBGraphicsPolygonItem(polygon);
UBGraphicsStroke *stroke = new UBGraphicsStroke();
graphicsPolygon->setStroke(stroke);
graphicsPolygon->setBrush(brush);
QTransform transform;
QString textTransform = element.attribute(aTransform);
graphicsPolygon->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, graphicsPolygon);
}
mCurrentScene->addItem(graphicsPolygon);
graphicsPolygon->setUuid(itemUuid);
mRefToUuidMap.insert(element.attribute(aId), itemUuid);
}
else // simple CFF
{
QSvgGenerator *generator = createSvgGenerator(width + pen.width(), height + pen.width());
QPainter painter;
painter.begin(generator); //drawing to svg tmp file
painter.translate(pen.widthF() / 2 - x1, pen.widthF() / 2 - y1);
painter.setBrush(brush);
painter.setPen(pen);
painter.drawPolygon(polygon);
painter.end();
//add resulting svg file to scene
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
svgItem->setUuid(QUuid(uuid));
QTransform transform;
QString textTransform = element.attribute(aTransform);
svgItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, svgItem);
}
repositionSvgItem(svgItem, width +strokeWidth, height + strokeWidth, x1 - strokeWidth/2 + transform.m31(), y1 + strokeWidth/2 + transform.m32(), transform);
hashSceneItem(element, svgItem);
if (mGSectionContainer)
{
addItemToGSection(svgItem);
}
delete generator;
}
return true;
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTextAttributes(const QDomElement &element,
qreal &fontSize, QColor &fontColor, QString &fontFamily,
QString &fontStretch, bool &italic, int &fontWeight,
int &textAlign, QTransform &fontTransform)
{
//consider inch has 72 liens
//since svg font size is given in pixels, divide it by pixels per line
QString fontSz = element.attribute(aFontSize);
if (!fontSz.isNull()) fontSize = fontSz.toDouble() * 72 / QApplication::desktop()->physicalDpiY();
QString fontColorText = element.attribute(aFill);
if (!fontColorText.isNull()) fontColor = colorFromString(fontColorText);
QString fontFamilyText = element.attribute(aFontfamily);
if (!fontFamilyText.isNull()) fontFamily = fontFamilyText;
QString fontStretchText = element.attribute(aFontstretch);
if (!fontStretchText.isNull()) fontStretch = fontStretchText;
if (!element.attribute(aFontstyle).isNull())
italic = (element.attribute(aFontstyle) == "italic");
QString weight = element.attribute(aFontweight);
if (!weight.isNull()) {
if (weight == "normal") fontWeight = QFont::Normal;
else if (weight == "light") fontWeight = QFont::Light;
else if (weight == "demibold") fontWeight = QFont::DemiBold;
else if (weight == "bold") fontWeight = QFont::Bold;
else if (weight == "black") fontWeight = QFont::Black;
}
QString align = element.attribute(aTextalign);
if (!align.isNull()) {
if (align == "middle" || align == "center") textAlign = Qt::AlignHCenter;
else if (align == "start") textAlign = Qt::AlignLeft;
else if (align == "end") textAlign = Qt::AlignRight;
}
if (!element.attribute(aTransform).isNull())
fontTransform = transformFromString(element.attribute(aTransform));
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::readTextBlockAttr(const QDomElement &element, QTextBlockFormat &format)
{
QString fontStretchText = element.attribute(aFontstretch);
if (!fontStretchText.isNull()) format.setAlignment(Qt::AlignJustify);
QString align = element.attribute(aTextalign);
if (!align.isNull()) {
if (align == "middle" || align == "center") format.setAlignment(Qt::AlignHCenter);
else if (align == "start") format.setAlignment(Qt::AlignLeft);
else if (align == "end") format.setAlignment(Qt::AlignRight);
else if (align == "justify") format.setAlignment(Qt::AlignJustify);
}
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::readTextCharAttr(const QDomElement &element, QTextCharFormat &format)
{
QString fontSz = element.attribute(aFontSize);
if (!fontSz.isNull()) {
qreal fontSize = fontSz.remove("pt").toDouble();
format.setFontPointSize(fontSize);
}
QString fontColorText = element.attribute(aFill);
if (!fontColorText.isNull()) {
QColor fontColor = colorFromString(fontColorText);
if (fontColor.isValid()) format.setForeground(fontColor);
}
QString fontFamilyText = element.attribute(aFontfamily);
if (!fontFamilyText.isNull()) {
format.setFontFamily(fontFamilyText);
}
if (!element.attribute(aFontstyle).isNull()) {
bool italic = (element.attribute(aFontstyle) == "italic");
format.setFontItalic(italic);
}
QString weight = element.attribute(aFontweight);
if (!weight.isNull()) {
if (weight == "normal") format.setFontWeight(QFont::Normal);
else if (weight == "light") format.setFontWeight(QFont::Light);
else if (weight == "demibold") format.setFontWeight(QFont::DemiBold);
else if (weight == "bold") format.setFontWeight(QFont::Bold);
else if (weight == "black") format.setFontWeight(QFont::Black);
}
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgText(const QDomElement &element)
{
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
qreal fontSize = 12;
QColor fontColor(qApp->palette().foreground().color());
QString fontFamily = "Arial";
QString fontStretch = "normal";
bool italic = false;
int fontWeight = QFont::Normal;
int textAlign = Qt::AlignLeft;
QTransform fontTransform;
parseTextAttributes(element, fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
QFont startFont(fontFamily, fontSize, fontWeight, italic);
height = QFontMetrics(startFont).height();
width = QFontMetrics(startFont).width(element.text()) + 5;
QSvgGenerator *generator = createSvgGenerator(width, height);
QPainter painter;
painter.begin(generator);
painter.setFont(startFont);
qreal curY = 0.0;
qreal curX = 0.0;
qreal linespacing = QFontMetricsF(painter.font()).leading();
// remember if text area has transform
// QString transformString;
QTransform transform = fontTransform;
QRectF lastDrawnTextBoundingRect;
//parse text area tags
//recursive call any tspan in text svg element
parseTSpan(element, painter
, curX, curY, width, height, linespacing, lastDrawnTextBoundingRect
, fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
painter.end();
//add resulting svg file to scene
UBGraphicsSvgItem *svgItem = mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName()));
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
svgItem->setUuid(QUuid(uuid));
svgItem->resetTransform();
repositionSvgItem(svgItem, width, height, x + transform.m31(), y + transform.m32(), transform);
hashSceneItem(element, svgItem);
if (mGSectionContainer)
{
addItemToGSection(svgItem);
}
delete generator;
return true;
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTSpan(const QDomElement &parent, QPainter &painter
, qreal &curX, qreal &curY, qreal &width, qreal &height, qreal &linespacing, QRectF &lastDrawnTextBoundingRect
, qreal &fontSize, QColor &fontColor, QString &fontFamily, QString &fontStretch, bool &italic
, int &fontWeight, int &textAlign, QTransform &fontTransform)
{
QDomNode curNode = parent.firstChild();
while (!curNode.isNull()) {
if (curNode.toElement().tagName() == tTspan) {
QDomElement curTSpan = curNode.toElement();
parseTextAttributes(curTSpan, fontSize, fontColor, fontFamily, fontStretch, italic
, fontWeight, textAlign, fontTransform);
painter.setFont(QFont(fontFamily, fontSize, fontWeight, italic));
painter.setPen(fontColor);
linespacing = QFontMetricsF(painter.font()).leading();
parseTSpan(curTSpan, painter
, curX, curY, width, height, linespacing, lastDrawnTextBoundingRect
, fontSize, fontColor, fontFamily, fontStretch, italic, fontWeight, textAlign, fontTransform);
} else if (curNode.nodeType() == QDomNode::CharacterDataNode
|| curNode.nodeType() == QDomNode::CDATASectionNode
|| curNode.nodeType() == QDomNode::TextNode) {
QDomCharacterData textData = curNode.toCharacterData();
QString text = textData.data().trimmed();
// width = painter.fontMetrics().width(text);
//get bounding rect to obtain desired text height
lastDrawnTextBoundingRect = painter.boundingRect(QRectF(curX, curY, width, height - curY), textAlign|Qt::TextWordWrap, text);
painter.drawText(curX, curY, width, lastDrawnTextBoundingRect.height(), textAlign|Qt::TextWordWrap, text);
curX += lastDrawnTextBoundingRect.x() + lastDrawnTextBoundingRect.width();
} else if (curNode.nodeType() == QDomNode::ElementNode
&& curNode.toElement().tagName() == tBreak) {
curY += lastDrawnTextBoundingRect.height() + linespacing;
curX = 0.0;
lastDrawnTextBoundingRect = QRectF(0,0,0,0);
}
curNode = curNode.nextSibling();
}
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTSpan(const QDomElement &element, QTextCursor &cursor
, QTextBlockFormat &blockFormat, QTextCharFormat &charFormat)
{
QDomNode curNode = element.firstChild();
while (!curNode.isNull()) {
if (curNode.toElement().tagName() == tTspan) {
QDomElement curTspan = curNode.toElement();
readTextBlockAttr(curTspan, blockFormat);
readTextCharAttr(curTspan, charFormat);
cursor.setBlockFormat(blockFormat);
cursor.setCharFormat(charFormat);
parseTSpan(curTspan, cursor, blockFormat, charFormat);
} else if (curNode.nodeType() == QDomNode::CharacterDataNode
|| curNode.nodeType() == QDomNode::CDATASectionNode
|| curNode.nodeType() == QDomNode::TextNode) {
QDomCharacterData textData = curNode.toCharacterData();
QString text = textData.data().trimmed();
cursor.insertText(text, charFormat);
} else if (curNode.nodeType() == QDomNode::ElementNode
&& curNode.toElement().tagName() == tBreak) {
cursor.insertBlock();
}
curNode = curNode.nextSibling();
}
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgTextarea(const QDomElement &element)
{
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
QTextBlockFormat blockFormat;
blockFormat.setAlignment(Qt::AlignLeft);
QTextCharFormat textFormat;
// default values
textFormat.setFontPointSize(12);
textFormat.setForeground(qApp->palette().foreground().color());
textFormat.setFontFamily("Arial");
textFormat.setFontItalic(false);
textFormat.setFontWeight(QFont::Normal);
// readed values
readTextBlockAttr(element, blockFormat);
readTextCharAttr(element, textFormat);
QTextDocument doc;
doc.setPlainText("");
QTextCursor tCursor(&doc);
tCursor.setBlockFormat(blockFormat);
tCursor.setCharFormat(textFormat);
parseTSpan(element, tCursor, blockFormat, textFormat);
UBGraphicsTextItem *svgItem = mCurrentScene->addTextHtml(doc.toHtml());
svgItem->resize(width, height);
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
svgItem->setUuid(QUuid(uuid));
QTransform transform;
QString textTransform = element.attribute(aTransform);
svgItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, svgItem);
}
//by default all the textAreas are not editable
UBGraphicsTextItemDelegate *curDelegate = dynamic_cast<UBGraphicsTextItemDelegate*>(svgItem->Delegate());
if (curDelegate) {
curDelegate->setEditable(false);
}
repositionSvgItem(svgItem, width, height, x + transform.m31(), y + transform.m32(), transform);
hashSceneItem(element, svgItem);
if (mGSectionContainer)
{
addItemToGSection(svgItem);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgImage(const QDomElement &element)
{
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
QString itemRefPath = element.attribute(aHref);
QPixmap pix;
if (!itemRefPath.isNull()) {
QString imagePath = pwdContent + "/" + itemRefPath;
if (!QFile::exists(imagePath)) {
qDebug() << "can't load file" << pwdContent + "/" + itemRefPath << "maybe file corrupted";
return false;
} else {
// qDebug() << "size of file" << itemRefPath << QFileInfo(itemRefPath).size();
}
pix.load(imagePath);
if (pix.isNull()) {
qDebug() << "can't create pixmap for file" << pwdContent + "/" + itemRefPath << "maybe format does not supported";
}
}
UBGraphicsPixmapItem *pixItem = mCurrentScene->addPixmap(pix, NULL);
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
pixItem->setUuid(QUuid(uuid));
QTransform transform;
QString textTransform = element.attribute(aTransform);
pixItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, pixItem);
}
repositionSvgItem(pixItem, width, height, x + transform.m31(), y + transform.m32(), transform);
hashSceneItem(element, pixItem);
if (mGSectionContainer)
{
addItemToGSection(pixItem);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgFlash(const QDomElement &element)
{
QString itemRefPath = element.attribute(aHref);
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
qreal width = element.attribute(aWidth).toDouble();
qreal height = element.attribute(aHeight).toDouble();
QUrl urlPath;
QString flashPath;
if (!itemRefPath.isNull()) {
flashPath = pwdContent + "/" + itemRefPath;
if (!QFile::exists(flashPath)) {
qDebug() << "can't load file" << pwdContent + "/" + itemRefPath << "maybe file corrupted";
return false;
}
urlPath = QUrl::fromLocalFile(flashPath);
}
QDir tmpFlashDir(mTmpFlashDir);
if (!tmpFlashDir.exists()) {
qDebug() << "Can't create temporary directory to put flash";
return false;
}
QString flashUrl = UBGraphicsW3CWidgetItem::createNPAPIWrapperInDir(flashPath, tmpFlashDir, "application/x-shockwave-flash"
,QSize(mCurrentSceneRect.width(), mCurrentSceneRect.height()));
UBGraphicsWidgetItem *flashItem = mCurrentScene->addW3CWidget(QUrl::fromLocalFile(flashUrl));
flashItem->setSourceUrl(urlPath);
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
flashItem->setUuid(QUuid(uuid));
QTransform transform;
QString textTransform = element.attribute(aTransform);
flashItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, flashItem);
}
repositionSvgItem(flashItem, width, height, x + transform.m31(), y + transform.m32(), transform);
hashSceneItem(element, flashItem);
if (mGSectionContainer)
{
addItemToGSection(flashItem);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgAudio(const QDomElement &element)
{
QDomElement parentOfAudio = element.firstChild().toElement();
qreal x = parentOfAudio.attribute(aX).toDouble();
qreal y = parentOfAudio.attribute(aY).toDouble();
QString itemRefPath = element.attribute(aHref);
QUrl concreteUrl;
if (!itemRefPath.isNull()) {
QString audioPath = pwdContent + "/" + itemRefPath;
if (!QFile::exists(audioPath)) {
qDebug() << "can't load file" << pwdContent + "/" + itemRefPath << "maybe file corrupted";
return false;
}
concreteUrl = QUrl::fromLocalFile(audioPath);
}
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
QString destFile;
bool b = UBPersistenceManager::persistenceManager()->addFileToDocument(
mCurrentScene->document(),
concreteUrl.toLocalFile(),
UBPersistenceManager::audioDirectory,
QUuid(uuid),
destFile);
if (!b)
{
return false;
}
concreteUrl = QUrl::fromLocalFile(destFile);
UBGraphicsMediaItem *audioItem = mCurrentScene->addAudio(concreteUrl, false);
QTransform transform;
QString textTransform = parentOfAudio.attribute(aTransform);
audioItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, audioItem);
}
repositionSvgItem(audioItem, audioItem->boundingRect().width(), audioItem->boundingRect().height(), x + transform.m31(), y + transform.m32(), transform);
hashSceneItem(element, audioItem);
if (mGSectionContainer)
{
addItemToGSection(audioItem);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgVideo(const QDomElement &element)
{
QString itemRefPath = element.attribute(aHref);
if (itemRefPath.startsWith(tFlash + "/") && itemRefPath.endsWith(".swf")) {
if (parseSvgFlash(element)) return true;
else return false;
}
qreal x = element.attribute(aX).toDouble();
qreal y = element.attribute(aY).toDouble();
QUrl concreteUrl;
if (!itemRefPath.isNull()) {
QString videoPath = pwdContent + "/" + itemRefPath;
if (!QFile::exists(videoPath)) {
qDebug() << "can't load file" << pwdContent + "/" + itemRefPath << "maybe file corrupted";
return false;
}
concreteUrl = QUrl::fromLocalFile(videoPath);
}
QString uuid = QUuid::createUuid().toString();
mRefToUuidMap.insert(element.attribute(aId), uuid);
QString destFile;
bool b = UBPersistenceManager::persistenceManager()->addFileToDocument(
mCurrentScene->document(),
concreteUrl.toLocalFile(),
UBPersistenceManager::videoDirectory,
QUuid(uuid),
destFile);
if (!b)
{
return false;
}
concreteUrl = QUrl::fromLocalFile(destFile);
UBGraphicsMediaItem *videoItem = mCurrentScene->addVideo(concreteUrl, false);
QTransform transform;
QString textTransform = element.attribute(aTransform);
videoItem->resetTransform();
if (!textTransform.isNull()) {
transform = transformFromString(textTransform, videoItem);
}
repositionSvgItem(videoItem, videoItem->boundingRect().width(), videoItem->boundingRect().height(), x + transform.m31(), y + transform.m32(), transform);
hashSceneItem(element, videoItem);
if (mGSectionContainer)
{
addItemToGSection(videoItem);
}
return true;
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgSectionAttr(const QDomElement &svgSection)
{
getViewBoxDimenstions(svgSection.attribute(aViewbox));
mSize = QSize(svgSection.attribute(aWidth).toInt(),
svgSection.attribute(aHeight).toInt());
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::addItemToGSection(QGraphicsItem *item)
{
mGSectionContainer->addToGroup(item);
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::hashSceneItem(const QDomElement &element, UBGraphicsItem *item)
{
// adding element pointer to hash to refer if needed
QString key = element.attribute(aId);
if (!key.isNull()) {
persistedItems.insert(key, item);
}
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgElement(const QDomElement &parent)
{
QString tagName = parent.tagName();
if (parent.namespaceURI() != svgNS) {
qWarning() << "Incorrect namespace, error at content file, line number" << parent.lineNumber();
//return false;
}
if (tagName == tG && !parseGSection(parent)) return false;
else if (tagName == tSwitch && !parseSvgSwitchSection(parent)) return false;
else if (tagName == tRect && !parseSvgRect(parent)) return false;
else if (tagName == tEllipse && !parseSvgEllipse(parent)) return false;
else if (tagName == tPolygon && !parseSvgPolygon(parent)) return false;
else if (tagName == tPolyline && !parseSvgPolyline(parent)) return false;
else if (tagName == tText && !parseSvgText(parent)) return false;
else if (tagName == tTextarea && !parseSvgTextarea(parent)) return false;
else if (tagName == tImage && !parseSvgImage(parent)) return false;
else if (tagName == tFlash && !parseSvgFlash(parent)) return false;
else if (tagName == tAudio && !parseSvgAudio(parent)) return false;
else if (tagName == tVideo && !parseSvgVideo(parent)) return false;
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPage(const QDomElement &parent)
{
createNewScene();
QDomElement currentSvgElement = parent.firstChildElement();
while (!currentSvgElement.isNull()) {
if (!parseSvgElement(currentSvgElement))
return false;
currentSvgElement = currentSvgElement.nextSiblingElement();
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvgPageset(const QDomElement &parent)
{
QDomElement currentPage = parent.firstChildElement(tPage);
while (!currentPage.isNull()) {
if (!parseSvgPage(currentPage))
return false;
currentPage = currentPage.nextSiblingElement(tPage);
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbMeta(const QDomElement &element)
{
if (element.namespaceURI() != iwbNS) {
qWarning() << "incorrect meta namespace, incorrect document";
//return false;
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvg(const QDomElement &svgSection)
{
if (svgSection.namespaceURI() != svgNS) {
qWarning() << "incorrect svg namespace, incorrect document";
// return false;
}
parseSvgSectionAttr(svgSection);
QDomElement currentSvg = svgSection.firstChildElement();
if (currentSvg.tagName() != tPageset) {
parseSvgPage(svgSection);
} else if (currentSvg.tagName() == tPageset){
parseSvgPageset(currentSvg);
}
return true;
}
UBGraphicsGroupContainerItem *UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbGroup(QDomElement &parent)
{
//TODO. Create groups from elements parsed by parseIwbElement() function
if (parent.namespaceURI() != iwbNS) {
qWarning() << "incorrect iwb group namespace, incorrect document";
// return false;
}
UBGraphicsGroupContainerItem *group = new UBGraphicsGroupContainerItem();
QMultiMap<QString, UBGraphicsPolygonItem *> strokesGroupsContainer;
QList<QGraphicsItem *> groupContainer;
QString currentStrokeIdentifier;
QDomElement currentStrokeElement = parent.firstChildElement();
while (!currentStrokeElement.isNull())
{
if (tGroup == currentStrokeElement.tagName())
group->addToGroup(parseIwbGroup(currentStrokeElement));
else
{
QString ref = currentStrokeElement.attribute(aRef);
QString uuid = mRefToUuidMap[ref];
if (!uuid.isEmpty())
{
if (ref.size() > QUuid().toString().length()) // create stroke group
{
currentStrokeIdentifier = ref.left(QUuid().toString().length()-1);
UBGraphicsPolygonItem *strokeByUuid = qgraphicsitem_cast<UBGraphicsPolygonItem *>(mCurrentScene->itemForUuid(QUuid(ref.right(QUuid().toString().length()))));
if (strokeByUuid)
strokesGroupsContainer.insert(currentStrokeIdentifier, strokeByUuid);
}
else // single elements in group
groupContainer.append(mCurrentScene->itemForUuid(QUuid(uuid)));
}
}
currentStrokeElement = currentStrokeElement.nextSiblingElement();
}
foreach (QString key, strokesGroupsContainer.keys().toSet())
{
UBGraphicsStrokesGroup* pStrokesGroup = new UBGraphicsStrokesGroup();
UBGraphicsStroke *currentStroke = new UBGraphicsStroke();
foreach(UBGraphicsPolygonItem* poly, strokesGroupsContainer.values(key))
{
if (poly)
{
mCurrentScene->removeItem(poly);
mCurrentScene->removeItemFromDeletion(poly);
poly->setStrokesGroup(pStrokesGroup);
poly->setStroke(currentStroke);
pStrokesGroup->addToGroup(poly);
}
}
if (currentStroke->polygons().empty()){
delete currentStroke;
currentStroke = NULL;
}
if (pStrokesGroup->childItems().count())
mCurrentScene->addItem(pStrokesGroup);
else{
delete pStrokesGroup;
pStrokesGroup = NULL;
}
if (pStrokesGroup)
{
QGraphicsItem *strokeGroup = qgraphicsitem_cast<QGraphicsItem *>(pStrokesGroup);
groupContainer.append(strokeGroup);
}
}
foreach(QGraphicsItem* item, groupContainer)
group->addToGroup(item);
if (group->childItems().count())
{
mCurrentScene->addItem(group);
if (1 == group->childItems().count())
{
group->destroy(false);
}
}
return group;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::strToBool(QString str)
{
return str == "true";
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbElement(QDomElement &element)
{
if (element.namespaceURI() != iwbNS) {
qWarning() << "incorrect iwb element namespace, incorrect document";
// return false;
}
bool locked = false;
bool isEditableItem = false;
bool isEditable = false; //Text items to convert to UBGraphicsTextItem only
QString IDRef = element.attribute(aRef);
if (!IDRef.isNull()) {
element.hasAttribute(aBackground) ? strToBool(element.attribute(aBackground)) : false;
locked = element.hasAttribute(aBackground) ? strToBool(element.attribute(aBackground)) : false;
isEditableItem = element.hasAttribute(aEditable);
if (isEditableItem)
isEditable = strToBool(element.attribute(aEditable));
UBGraphicsItem *referedItem(0);
QHash<QString, UBGraphicsItem*>::iterator iReferedItem;
iReferedItem = persistedItems.find(IDRef);
if (iReferedItem != persistedItems.end()) {
referedItem = *iReferedItem;
referedItem->Delegate()->lock(locked);
}
if (isEditableItem) {
UBGraphicsTextItemDelegate *textDelegate = dynamic_cast<UBGraphicsTextItemDelegate*>(referedItem->Delegate());
if (textDelegate) {
textDelegate->setEditable(isEditable);
}
}
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc()
{
QDomElement currentTopElement = mDOMdoc.documentElement().firstChildElement();
while (!currentTopElement.isNull()) {
QString tagName = currentTopElement.tagName();
if (tagName == tMeta && !parseIwbMeta(currentTopElement)) return false;
else if (tagName == tSvg && !parseSvg(currentTopElement)) return false;
else if (tagName == tGroup && !parseIwbGroup(currentTopElement)) return false;
else if (tagName == tElement && !parseIwbElement(currentTopElement)) return false;
currentTopElement = currentTopElement.nextSiblingElement();
}
if (!persistScenes()) return false;
return true;
}
void UBCFFSubsetAdaptor::UBCFFSubsetReader::repositionSvgItem(QGraphicsItem *item, qreal width, qreal height,
qreal x, qreal y,
QTransform &transform)
{
//First using viebox coordinates, then translate them to scene coordinates
QRectF itemBounds = item->boundingRect();
qreal xScale = width / itemBounds.width();
qreal yScale = height / itemBounds.height();
qreal fullScaleX = mVBTransFactor * xScale;
qreal fullScaleY = mVBTransFactor * yScale;
QPointF oldVector((x - transform.dx()), (y - transform.dy()));
QTransform rTransform;
QPointF newVector = rTransform.map(oldVector);
QTransform tr = item->sceneTransform();
item->setTransform(rTransform.scale(fullScaleX, fullScaleY), true);
tr = item->sceneTransform();
QPoint pos;
if (UBGraphicsTextItem::Type == item->type())
pos = QPoint((int)((x + mShiftVector.x() + (newVector - oldVector).x())), (int)((y +mShiftVector.y() + (newVector - oldVector).y()) * mVBTransFactor));
else
pos = QPoint((int)((x + mShiftVector.x() + (newVector - oldVector).x()) * mVBTransFactor), (int)((y +mShiftVector.y() + (newVector - oldVector).y()) * mVBTransFactor));
item->setPos(pos);
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::createNewScene()
{
mCurrentScene = UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mProxy, mProxy->pageCount(), false);
mCurrentScene->setSceneRect(mViewBox);
if ((mCurrentScene->sceneRect().topLeft().x() >= 0) || (mCurrentScene->sceneRect().topLeft().y() >= 0)) {
mShiftVector = -mViewBox.center();
}
mCurrentSceneRect = mViewBox;
mVBTransFactor = qMin(mCurrentScene->normalizedSceneRect().width() / mViewPort.width(),
mCurrentScene->normalizedSceneRect().height() / mViewPort.height());
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::persistCurrentScene()
{
if (mCurrentScene != 0 && mCurrentScene->isModified())
{
UBThumbnailAdaptor::persistScene(mProxy, mCurrentScene, mProxy->pageCount() - 1);
UBSvgSubsetAdaptor::persistScene(mProxy, mCurrentScene, mProxy->pageCount() - 1);
mCurrentScene->setModified(false);
mCurrentScene = 0;
}
return true;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::persistScenes()
{
if (!mProxy->pageCount()) {
qDebug() << "No pages created";
return false;
}
for (int i = 0; i < mProxy->pageCount(); i++) {
mCurrentScene = UBPersistenceManager::persistenceManager()->getDocumentScene(mProxy, i);
if (!mCurrentScene) {
qDebug() << "can't allocate scene, loading failed";
return false;
}
UBSvgSubsetAdaptor::persistScene(mProxy, mCurrentScene, i);
UBGraphicsScene *tmpScene = UBSvgSubsetAdaptor::loadScene(mProxy, i);
tmpScene->setModified(true);
UBThumbnailAdaptor::persistScene(mProxy, tmpScene, i);
mCurrentScene->setModified(false);
}
return true;
}
QColor UBCFFSubsetAdaptor::UBCFFSubsetReader::colorFromString(const QString& clrString)
{
//init regexp with pattern
//pattern corresponds to strings like 'rgb(1,2,3) or rgb(10%,20%,30%)'
QRegExp regexp("rgb\\(([0-9]+%{0,1}),([0-9]+%{0,1}),([0-9]+%{0,1})\\)");
if (regexp.exactMatch(clrString))
{
if (regexp.capturedTexts().count() == 4 && regexp.capturedTexts().at(0).length() == clrString.length())
{
int r = regexp.capturedTexts().at(1).toInt();
if (regexp.capturedTexts().at(1).indexOf("%") != -1)
r = r * 255 / 100;
int g = regexp.capturedTexts().at(2).toInt();
if (regexp.capturedTexts().at(2).indexOf("%") != -1)
g = g * 255 / 100;
int b = regexp.capturedTexts().at(3).toInt();
if (regexp.capturedTexts().at(3).indexOf("%") != -1)
b = b * 255 / 100;
return QColor(r, g, b);
}
else
return QColor();
}
else
return QColor(clrString);
}
QTransform UBCFFSubsetAdaptor::UBCFFSubsetReader::transformFromString(const QString trString, QGraphicsItem *item)
{
qreal dxr = 0.0;
qreal dyr = 0.0;
qreal dx = 0.0;
qreal dy = 0.0;
qreal angle = 0.0;
QTransform tr;
foreach(QString trStr, trString.split(" ", QString::SkipEmptyParts))
{
//check pattern for strings like 'rotate(10)'
QRegExp regexp("rotate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *\\)");
if (regexp.exactMatch(trStr)) {
angle = regexp.capturedTexts().at(1).toDouble();
if (item)
{
item->setTransformOriginPoint(QPointF(0, 0));
item->rotate(angle);
}
continue;
};
//check pattern for strings like 'rotate(10,20,20)' or 'rotate(10.1,10.2,34.2)'
regexp.setPattern("rotate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *, *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *, *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *\\)");
if (regexp.exactMatch(trStr)) {
angle = regexp.capturedTexts().at(1).toDouble();
dxr = regexp.capturedTexts().at(2).toDouble();
dyr = regexp.capturedTexts().at(3).toDouble();
if (item)
{
item->setTransformOriginPoint(QPointF(dxr, dyr)-item->pos());
item->rotate(angle);
}
continue;
}
//check pattern for strings like 'translate(11.0, 12.34)'
regexp.setPattern("translate\\( *([-+]{0,1}[0-9]*\\.{0,1}[0-9]*) *,*([-+]{0,1}[0-9]*\\.{0,1}[0-9]*)*\\)");
if (regexp.exactMatch(trStr)) {
dx = regexp.capturedTexts().at(1).toDouble();
dy = regexp.capturedTexts().at(2).toDouble();
tr.translate(dx,dy);
continue;
}
}
return tr;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getViewBoxDimenstions(const QString& viewBox)
{
QStringList capturedTexts = viewBox.split(" ", QString::SkipEmptyParts);
if (capturedTexts.count())
{
if (4 == capturedTexts.count())
{
mViewBox = QRectF(capturedTexts.at(0).toDouble(), capturedTexts.at(1).toDouble(), capturedTexts.at(2).toDouble(), capturedTexts.at(3).toDouble());
mViewPort = mViewBox;
mViewPort.translate(- mViewPort.center());
mViewBoxCenter.setX(mViewBox.width() / 2);
mViewBoxCenter.setY(mViewBox.height() / 2);
return true;
}
}
mViewBox = QRectF(0, 0, 1000, 1000);
mViewBoxCenter = QPointF(500, 500);
return false;
}
QSvgGenerator* UBCFFSubsetAdaptor::UBCFFSubsetReader::createSvgGenerator(qreal width, qreal height)
{
QSvgGenerator* generator = new QSvgGenerator();
// qWarning() << QString("Making generator with file %1, size (%2, %3) and viewbox (%4 %5 %6 %7)").arg(mTempFilePath)
// .arg(width).arg(height).arg(0.0).arg(0.0).arg(width).arg(width);
generator->setResolution(QApplication::desktop()->physicalDpiY());
generator->setFileName(mTempFilePath);
generator->setSize(QSize(width, height));
generator->setViewBox(QRectF(0, 0, width, height));
return generator;
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getTempFileName()
{
int tmpNumber = 0;
QDir rootDir;
while (true)
{
mTempFilePath = QString("%1/sanksvg%2.%3")
.arg(rootDir.tempPath())
.arg(QDateTime::currentDateTime().toString("dd_MM_yyyy_HH-mm"))
.arg(tmpNumber);
if (!QFile::exists(mTempFilePath))
return true;
tmpNumber++;
if (tmpNumber == 100000)
{
qWarning() << "Import failed. Failed to create temporary file for svg objects";
return false;
}
}
}
bool UBCFFSubsetAdaptor::UBCFFSubsetReader::createTempFlashPath()
{
int tmpNumber = 0;
QDir systemTmp = QDir::temp();
while (true) {
QString dirName = QString("SankTmpFlash%1.%2")
.arg(QDateTime::currentDateTime().toString("dd_MM_yyyy_HH-mm"))
.arg(tmpNumber++);
if (!systemTmp.exists(dirName)) {
if (systemTmp.mkdir(dirName)) {
mTmpFlashDir = QDir(systemTmp.absolutePath() + "/" + dirName);
return true;
} else {
qDebug() << "Can't create temporary dir maybe due to permissions";
return false;
}
} else if (tmpNumber == 1000) {
qWarning() << "Import failed. Failed to create temporary file for svg objects";
return false;
}
}
return true;
}
UBCFFSubsetAdaptor::UBCFFSubsetReader::~UBCFFSubsetReader()
{
// QList<int> pages;
// for (int i = 0; i < mProxy->pageCount(); i++) {
// pages << i;
// }
// UBPersistenceManager::persistenceManager()->deleteDocumentScenes(mProxy, pages);
}
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBCFFSUBSETADAPTOR_H
#define UBCFFSUBSETADAPTOR_H
#include <QtXml>
#include <QString>
#include <QStack>
#include <QDomDocument>
#include <QHash>
class UBDocumentProxy;
class UBGraphicsScene;
class QSvgGenerator;
class UBGraphicsSvgItem;
class UBGraphicsPixmapItem;
class UBGraphicsItemDelegate;
class QTransform;
class QPainter;
class UBGraphicsItem;
class QGraphicsItem;
class QTextBlockFormat;
class QTextCharFormat;
class QTextCursor;
class UBGraphicsStrokesGroup;
class UBCFFSubsetAdaptor
{
public:
UBCFFSubsetAdaptor();
static bool ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentProxy* pDocument);
private:
class UBCFFSubsetReader
{
public:
UBCFFSubsetReader(UBDocumentProxy *proxy, QFile *content);
~UBCFFSubsetReader();
UBDocumentProxy *mProxy;
QString pwdContent;
bool parse();
private:
QString mTempFilePath;
UBGraphicsScene *mCurrentScene;
QRectF mCurrentSceneRect;
QString mIndent;
QRectF mViewBox;
QRectF mViewPort;
qreal mVBTransFactor;
QPointF mViewBoxCenter;
QSize mSize;
QPointF mShiftVector;
bool mSvgGSectionIsOpened;
UBGraphicsGroupContainerItem *mGSectionContainer;
private:
QDomDocument mDOMdoc;
QDomNode mCurrentDOMElement;
QHash<QString, UBGraphicsItem*> persistedItems;
QMap<QString, QString> mRefToUuidMap;
QDir mTmpFlashDir;
void addItemToGSection(QGraphicsItem *item);
bool hashElements();
void addExtentionsToHash(QDomElement *parent, QDomElement *topGroup);
void hashSvg(QDomNode *parent, QString prefix = "");
void hashSiblingIwbElements(QDomElement *parent, QDomElement *topGroup = 0);
inline void parseSvgSectionAttr(const QDomElement &);
bool parseSvgPage(const QDomElement &parent);
bool parseSvgPageset(const QDomElement &parent);
bool parseSvgElement(const QDomElement &parent);
bool parseIwbMeta(const QDomElement &element);
bool parseSvg(const QDomElement &svgSection);
inline bool parseGSection(const QDomElement &element);
inline bool parseSvgSwitchSection(const QDomElement &element);
inline bool parseSvgRect(const QDomElement &element);
inline bool parseSvgEllipse(const QDomElement &element);
inline bool parseSvgPolygon(const QDomElement &element);
inline bool parseSvgPolyline(const QDomElement &element);
inline bool parseSvgText(const QDomElement &element);
inline bool parseSvgTextarea(const QDomElement &element);
inline bool parseSvgImage(const QDomElement &element);
inline bool parseSvgFlash(const QDomElement &element);
inline bool parseSvgAudio(const QDomElement &element);
inline bool parseSvgVideo(const QDomElement &element);
inline UBGraphicsGroupContainerItem *parseIwbGroup(QDomElement &parent);
inline bool parseIwbElement(QDomElement &element);
inline void parseTSpan(const QDomElement &parent, QPainter &painter
, qreal &curX, qreal &curY, qreal &width, qreal &height, qreal &linespacing, QRectF &lastDrawnTextBoundingRect
, qreal &fontSize, QColor &fontColor, QString &fontFamily, QString &fontStretch, bool &italic
, int &fontWeight, int &textAlign, QTransform &fontTransform);
inline void parseTSpan(const QDomElement &element, QTextCursor &cursor
, QTextBlockFormat &blockFormat, QTextCharFormat &charFormat);
inline void hashSceneItem(const QDomElement &element, UBGraphicsItem *item);
// to kill
inline void parseTextAttributes(const QDomElement &element, qreal &fontSize, QColor &fontColor,
QString &fontFamily, QString &fontStretch, bool &italic,
int &fontWeight, int &textAlign, QTransform &fontTransform);
inline void parseTextAttributes(const QDomElement &element, QFont &font, QColor);
inline void readTextBlockAttr(const QDomElement &element, QTextBlockFormat &format);
inline void readTextCharAttr(const QDomElement &element, QTextCharFormat &format);
//elements parsing methods
bool parseDoc();
bool createNewScene();
bool persistCurrentScene();
bool persistScenes();
// helper methods
void repositionSvgItem(QGraphicsItem *item, qreal width, qreal height,
qreal x, qreal y,
QTransform &transform);
QColor colorFromString(const QString& clrString);
QTransform transformFromString(const QString trString, QGraphicsItem *item = 0);
bool getViewBoxDimenstions(const QString& viewBox);
QSvgGenerator* createSvgGenerator(qreal width, qreal height);
bool getTempFileName();
inline bool strToBool(QString);
bool createTempFlashPath();
};
};
#endif // UBCFFSUBSETADAPTOR_H
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "UBExportCFF.h"
#include "UBCFFAdaptor.h"
#include "document/UBDocumentProxy.h"
#include "core/UBDocumentManager.h"
#include "core/UBApplication.h"
#include "core/memcheck.h"
UBExportCFF::UBExportCFF(QObject *parent)
: UBExportAdaptor(parent)
{
}
UBExportCFF::~UBExportCFF()
{
}
QString UBExportCFF::exportName()
{
return tr("Export to IWB");
}
QString UBExportCFF::exportExtention()
{
return QString(".iwb");
}
void UBExportCFF::persist(UBDocumentProxy* pDocument)
{
if (!pDocument)
return;
QString src = pDocument->persistencePath();
QString filename = askForFileName(pDocument, tr("Export as IWB File"));
if (filename.length() > 0)
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
if (mIsVerbose)
UBApplication::showMessage(tr("Exporting document..."));
UBCFFAdaptor toIWBExporter;
if (toIWBExporter.convertUBZToIWB(src, filename))
{
if (mIsVerbose)
UBApplication::showMessage(tr("Export successful."));
}
else
if (mIsVerbose)
UBApplication::showMessage(tr("Export failed."));
showErrorsList(toIWBExporter.getConversionMessages());
QApplication::restoreOverrideCursor();
}
}
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBExportCFF_H_
#define UBExportCFF_H_
#include <QtCore>
#include "UBExportAdaptor.h"
#include "frameworks/UBFileSystemUtils.h"
class UBDocumentProxy;
class UBExportCFF : public UBExportAdaptor
{
Q_OBJECT;
public:
UBExportCFF(QObject *parent = 0);
virtual ~UBExportCFF();
virtual QString exportName();
virtual QString exportExtention();
virtual void persist(UBDocumentProxy* pDocument);
};
#endif /* UBExportCFF_H_ */
\ No newline at end of file
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <QDir>
#include <QList>
#include "core/UBApplication.h"
#include "core/UBPersistenceManager.h"
#include "core/UBDocumentManager.h"
#include "core/UBPersistenceManager.h"
#include "document/UBDocumentProxy.h"
#include "domain/UBGraphicsPDFItem.h"
#include "frameworks/UBFileSystemUtils.h"
#include "pdf/PDFRenderer.h"
#include "UBCFFSubsetAdaptor.h"
#include "UBImportCFF.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"
UBImportCFF::UBImportCFF(QObject *parent)
: UBDocumentBasedImportAdaptor(parent)
{
// NOOP
}
UBImportCFF::~UBImportCFF()
{
// NOOP
}
QStringList UBImportCFF::supportedExtentions()
{
return QStringList("iwb");
}
QString UBImportCFF::importFileFilter()
{
QString filter = tr("Common File Format (");
QStringList formats = supportedExtentions();
bool isFirst = true;
foreach(QString format, formats)
{
if(isFirst)
isFirst = false;
else
filter.append(" ");
filter.append("*."+format);
}
filter.append(")");
return filter;
}
bool UBImportCFF::addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile)
{
QFileInfo fi(pFile);
UBApplication::showMessage(tr("Importing file %1...").arg(fi.baseName()), true);
// first unzip the file to the correct place
//TODO create temporary path for iwb file content
QString path = QDir::tempPath();
QString documentRootFolder = expandFileToDir(pFile, path);
QString contentFile;
if (documentRootFolder.isEmpty()) //if file has failed to unzip it is probably just xml file
contentFile = pFile.fileName();
else //get path to content xml (according to iwbcff specification)
contentFile = documentRootFolder.append("/content.xml");
if(!contentFile.length()){
UBApplication::showMessage(tr("Import of file %1 failed.").arg(fi.baseName()));
return false;
}
else{
//TODO convert expanded CFF file content to the destination document
//create destination document proxy
//fill metadata and save
UBDocumentProxy* destDocument = new UBDocumentProxy(UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath());
QDir dir;
dir.mkdir(destDocument->persistencePath());
//try to import cff to document
if (UBCFFSubsetAdaptor::ConvertCFFFileToUbz(contentFile, destDocument))
{
UBPersistenceManager::persistenceManager()->addDirectoryContentToDocument(destDocument->persistencePath(), pDocument);
UBFileSystemUtils::deleteDir(destDocument->persistencePath());
delete destDocument;
UBApplication::showMessage(tr("Import successful."));
return true;
}
else
{
UBFileSystemUtils::deleteDir(destDocument->persistencePath());
delete destDocument;
UBApplication::showMessage(tr("Import failed."));
return false;
}
}
}
QString UBImportCFF::expandFileToDir(const QFile& pZipFile, const QString& 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);
//create unique cff document root fodler
//use current date/time and temp number for folder name
QString documentRootFolder;
int tmpNumber = 0;
QDir rootDir;
while (true) {
QString tempPath = QString("%1/sank%2.%3")
.arg(pDir)
.arg(QDateTime::currentDateTime().toString("dd_MM_yyyy_HH-mm"))
.arg(tmpNumber);
if (!rootDir.exists(tempPath)) {
documentRootFolder = tempPath;
break;
}
tmpNumber++;
if (tmpNumber == 100000) {
qWarning() << "Import failed. Failed to create temporary directory for iwb file";
return "";
}
}
if (!rootDir.mkdir(documentRootFolder)) {
qWarning() << "Import failed. Couse: failed to create temp folder for cff package";
}
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 "";
// }
file.open(QIODevice::ReadOnly);
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);
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* UBImportCFF::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
//TODO create temporary path for iwb file content
QString path = QDir::tempPath();
QString documentRootFolder = expandFileToDir(pFile, path);
QString contentFile;
if (documentRootFolder.isEmpty())
//if file has failed to umzip it is probably just xml file
contentFile = pFile.fileName();
else
//get path to content xml
contentFile = QString("%1/content.xml").arg(documentRootFolder);
if(!contentFile.length()){
UBApplication::showMessage(tr("Import of file %1 failed.").arg(fi.baseName()));
return 0;
}
else{
//create destination document proxy
//fill metadata and save
UBDocumentProxy* destDocument = new UBDocumentProxy(UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath());
QDir dir;
dir.mkdir(destDocument->persistencePath());
if (pGroup.length() > 0)
destDocument->setMetaData(UBSettings::documentGroupName, pGroup);
if (fi.baseName() > 0)
destDocument->setMetaData(UBSettings::documentName, fi.baseName());
destDocument->setMetaData(UBSettings::documentVersion, UBSettings::currentFileVersion);
destDocument->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime()));
UBDocumentProxy* newDocument = NULL;
//try to import cff to document
if (UBCFFSubsetAdaptor::ConvertCFFFileToUbz(contentFile, destDocument))
{
newDocument = UBPersistenceManager::persistenceManager()->createDocumentFromDir(destDocument->persistencePath());
UBApplication::showMessage(tr("Import successful."));
}
else
{
UBFileSystemUtils::deleteDir(destDocument->persistencePath());
UBApplication::showMessage(tr("Import failed."));
}
delete destDocument;
if (documentRootFolder.length() != 0)
UBFileSystemUtils::deleteDir(documentRootFolder);
return newDocument;
}
}
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef UBIMPORTCFF_H
#define UBIMPORTCFF_H
#include <QtGui>
#include "UBImportAdaptor.h"
class UBDocumentProxy;
class UBImportCFF : public UBDocumentBasedImportAdaptor
{
Q_OBJECT;
public:
UBImportCFF(QObject *parent = 0);
virtual ~UBImportCFF();
virtual QStringList supportedExtentions();
virtual QString importFileFilter();
virtual bool addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile);
virtual UBDocumentProxy* importFile(const QFile& pFile, const QString& pGroup);
private:
QString expandFileToDir(const QFile& pZipFile, const QString& pDir);
};
#endif // UBIMPORTCFF_H
...@@ -11,13 +11,8 @@ HEADERS += src/adaptors/UBExportAdaptor.h\ ...@@ -11,13 +11,8 @@ HEADERS += src/adaptors/UBExportAdaptor.h\
src/adaptors/UBImportPDF.h \ src/adaptors/UBImportPDF.h \
src/adaptors/UBImportImage.h \ src/adaptors/UBImportImage.h \
src/adaptors/UBExportWeb.h \ src/adaptors/UBExportWeb.h \
src/adaptors/UBImportCFF.h \ src/adaptors/publishing/UBDocumentPublisher.h \
src/adaptors/UBExportCFF.h \
src/adaptors/UBCFFSubsetAdaptor.h
HEADERS += src/adaptors/publishing/UBDocumentPublisher.h \
src/adaptors/publishing/UBSvgSubsetRasterizer.h src/adaptors/publishing/UBSvgSubsetRasterizer.h
SOURCES += src/adaptors/UBExportAdaptor.cpp\ SOURCES += src/adaptors/UBExportAdaptor.cpp\
...@@ -32,10 +27,5 @@ SOURCES += src/adaptors/UBExportAdaptor.cpp\ ...@@ -32,10 +27,5 @@ SOURCES += src/adaptors/UBExportAdaptor.cpp\
src/adaptors/UBImportPDF.cpp \ src/adaptors/UBImportPDF.cpp \
src/adaptors/UBImportImage.cpp \ src/adaptors/UBImportImage.cpp \
src/adaptors/UBExportWeb.cpp \ src/adaptors/UBExportWeb.cpp \
src/adaptors/UBImportCFF.cpp \ src/adaptors/publishing/UBDocumentPublisher.cpp\
src/adaptors/UBExportCFF.cpp \
src/adaptors/UBCFFSubsetAdaptor.cpp \
src/adaptors/publishing/UBDocumentPublisher.cpp
SOURCES += \
src/adaptors/publishing/UBSvgSubsetRasterizer.cpp src/adaptors/publishing/UBSvgSubsetRasterizer.cpp
...@@ -32,11 +32,9 @@ ...@@ -32,11 +32,9 @@
#include "adaptors/UBExportFullPDF.h" #include "adaptors/UBExportFullPDF.h"
#include "adaptors/UBExportDocument.h" #include "adaptors/UBExportDocument.h"
#include "adaptors/UBExportWeb.h" #include "adaptors/UBExportWeb.h"
#include "adaptors/UBExportCFF.h"
#include "adaptors/UBImportDocument.h" #include "adaptors/UBImportDocument.h"
#include "adaptors/UBImportPDF.h" #include "adaptors/UBImportPDF.h"
#include "adaptors/UBImportImage.h" #include "adaptors/UBImportImage.h"
#include "adaptors/UBImportCFF.h"
#include "domain/UBGraphicsScene.h" #include "domain/UBGraphicsScene.h"
#include "domain/UBGraphicsSvgItem.h" #include "domain/UBGraphicsSvgItem.h"
...@@ -73,12 +71,10 @@ UBDocumentManager::UBDocumentManager(QObject *parent) ...@@ -73,12 +71,10 @@ UBDocumentManager::UBDocumentManager(QObject *parent)
QString dummyObjects = tr("objects"); QString dummyObjects = tr("objects");
QString dummyWidgets = tr("widgets"); QString dummyWidgets = tr("widgets");
UBExportCFF* cffExporter = new UBExportCFF(this);
UBExportFullPDF* exportFullPdf = new UBExportFullPDF(this); UBExportFullPDF* exportFullPdf = new UBExportFullPDF(this);
UBExportDocument* exportDocument = new UBExportDocument(this); UBExportDocument* exportDocument = new UBExportDocument(this);
mExportAdaptors.append(exportDocument); mExportAdaptors.append(exportDocument);
mExportAdaptors.append(exportFullPdf); mExportAdaptors.append(exportFullPdf);
mExportAdaptors.append(cffExporter);
UBImportDocument* documentImport = new UBImportDocument(this); UBImportDocument* documentImport = new UBImportDocument(this);
mImportAdaptors.append(documentImport); mImportAdaptors.append(documentImport);
...@@ -86,8 +82,6 @@ UBDocumentManager::UBDocumentManager(QObject *parent) ...@@ -86,8 +82,6 @@ UBDocumentManager::UBDocumentManager(QObject *parent)
mImportAdaptors.append(pdfImport); mImportAdaptors.append(pdfImport);
UBImportImage* imageImport = new UBImportImage(this); UBImportImage* imageImport = new UBImportImage(this);
mImportAdaptors.append(imageImport); mImportAdaptors.append(imageImport);
UBImportCFF* cffImport = new UBImportCFF(this);
mImportAdaptors.append(cffImport);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment