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 section
while(!htmlPNode.isNull())
{
// add 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 &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 &dstSvgList)
{
qDebug() << "|parsing g section";
QDomElement nextElement = element.firstChildElement();
if (nextElement.isNull()) {
qDebug() << "Empty g element";
errorStr = "EmptyGSection";
return false;
}
QMultiMap 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 layers;
QMapIterator 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 &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 &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 &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 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 &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 &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 &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 &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 &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 &dstList, int layer)
{
int elementLayer = (DEFAULT_LAYER == layer) ? DEFAULT_LAYER : layer;
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()
{
}