From 2f0eaca0f164b4d11e23626d4e99495e7d36d9e9 Mon Sep 17 00:00:00 2001 From: "ivan.ilyin" Date: Wed, 3 Aug 2011 10:41:54 +0300 Subject: [PATCH 1/4] Added subset adaptor for cff import (stubs only for now) --- src/adaptors/UBCFFSubsetAdaptor.cpp | 22 +++ src/adaptors/UBCFFSubsetAdaptor.h | 27 ++++ src/adaptors/UBImportCFF.cpp | 229 ++++++++++++++++++++++++++++ src/adaptors/UBImportCFF.h | 30 ++++ src/core/UBDocumentManager.cpp | 3 + 5 files changed, 311 insertions(+) create mode 100644 src/adaptors/UBCFFSubsetAdaptor.cpp create mode 100644 src/adaptors/UBCFFSubsetAdaptor.h create mode 100644 src/adaptors/UBImportCFF.cpp create mode 100644 src/adaptors/UBImportCFF.h diff --git a/src/adaptors/UBCFFSubsetAdaptor.cpp b/src/adaptors/UBCFFSubsetAdaptor.cpp new file mode 100644 index 00000000..a06b26fa --- /dev/null +++ b/src/adaptors/UBCFFSubsetAdaptor.cpp @@ -0,0 +1,22 @@ +#include "UBCFFSubsetAdaptor.h" +#include "document/UBDocumentProxy.h" + +UBCFFSubsetAdaptor::UBCFFSubsetAdaptor() +{ +} + +void UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFolder, QString &destinationFolder) +{ + //TODO create document proxy for destination file + // create document proxy with destination folder + // fill document proxy metadata + // create persistance manager to save data using proxy + // create UBCFFSubsetReader and make it parse cffSourceFolder +} + +UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy): + mReader(), mProxy(proxy) +{ + //TODO parse +} + diff --git a/src/adaptors/UBCFFSubsetAdaptor.h b/src/adaptors/UBCFFSubsetAdaptor.h new file mode 100644 index 00000000..34db3d80 --- /dev/null +++ b/src/adaptors/UBCFFSubsetAdaptor.h @@ -0,0 +1,27 @@ +#ifndef UBCFFSUBSETADAPTOR_H +#define UBCFFSUBSETADAPTOR_H + +#include +#include + +class UBDocumentProxy; + +class UBCFFSubsetAdaptor +{ +public: + UBCFFSubsetAdaptor(); + + static void ConvertCFFFileToUbz(QString &cffSourceFolder, QString &destinationFolder); + +private: + class UBCFFSubsetReader + { + public: + UBCFFSubsetReader(UBDocumentProxy *proxy); + + QXmlStreamReader mReader; + UBDocumentProxy *mProxy; + }; +}; + +#endif // UBCFFSUBSETADAPTOR_H diff --git a/src/adaptors/UBImportCFF.cpp b/src/adaptors/UBImportCFF.cpp new file mode 100644 index 00000000..5487a0d5 --- /dev/null +++ b/src/adaptors/UBImportCFF.cpp @@ -0,0 +1,229 @@ +#include +#include "UBImportCFF.h" +#include "document/UBDocumentProxy.h" + +#include "core/UBApplication.h" +#include "core/UBPersistenceManager.h" +#include "core/UBDocumentManager.h" + +#include "domain/UBGraphicsPDFItem.h" + +#include "pdf/PDFRenderer.h" + +#include "core/memcheck.h" + +#include "core/UBPersistenceManager.h" + +#include "UBCFFSubsetAdaptor.h" + +#include "quazip.h" +#include "quazipfile.h" +#include "quazipfileinfo.h" + +UBImportCFF::UBImportCFF(QObject *parent) + : UBImportAdaptor(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) +{ + //TODO add cff file import here +/* int res = UBDocumentManager::documentManager()->addImageAsPageToDocument(QStringList(QFileInfo(pFile).absoluteFilePath()), pDocument); + if (res == 0) + { + UBApplication::showMessage(tr("Image import failed.")); + return false; + } + else + { + UBApplication::showMessage(tr("Image import successful.")); + return true; + }*/ + return true; +} + +QString UBImportCFF::expandFileToDir(const QFile& pZipFile, const QString& pDir) +{ + + QDir rootDir(pDir); + QuaZip zip(pZipFile.fileName()); + + if(!zip.open(QuaZip::mdUnzip)) + { + qWarning() << "Import failed. Cause zip.open(): " << zip.getZipError(); + return ""; + } + + zip.setFileNameCodec("UTF-8"); + QuaZipFileInfo info; + QuaZipFile file(&zip); + + // TODO UB 4.x implement a mechanism that can replace an existing + // document based on the UID of the document. + bool createNewDocument = true; + QString documentRootFolder; + + // first we search the metadata.rdf to check the document properties + for(bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) + { + if(!zip.getCurrentFileInfo(&info)) + { + qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError(); + return ""; + } + + QFileInfo currentFileInfo(pDir + "/" + file.getActualFileName()); + } + + if (createNewDocument) + documentRootFolder = UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath(); + + + QFile out; + char c; + for(bool more=zip.goToFirstFile(); more; more=zip.goToNextFile()) + { + if(!zip.getCurrentFileInfo(&info)) + { + //TOD UB 4.3 O display error to user or use crash reporter + qWarning() << "Import failed. Cause: getCurrentFileInfo(): " << zip.getZipError(); + return ""; + } + + if(!file.open(QIODevice::ReadOnly)) + { + qWarning() << "Import failed. Cause: file.open(): " << zip.getZipError(); + return ""; + } + + if(file.getZipError()!= UNZ_OK) + { + qWarning() << "Import failed. Cause: file.getFileName(): " << zip.getZipError(); + return ""; + } + + QString newFileName = documentRootFolder + "/" + file.getActualFileName(); + QFileInfo newFileInfo(newFileName); + rootDir.mkpath(newFileInfo.absolutePath()); + + out.setFileName(newFileName); + out.open(QIODevice::WriteOnly); + + // Slow like hell (on GNU/Linux at least), but it is not my fault. + // Not ZIP/UNZIP package's fault either. + // The slowest thing here is out.putChar(c). + QByteArray outFileContent = file.readAll(); + if (out.write(outFileContent) == -1) + { + qWarning() << "Import failed. Cause: Unable to write file"; + out.close(); + return ""; + } + + while(file.getChar(&c)) + out.putChar(c); + + out.close(); + + if(file.getZipError()!=UNZ_OK) + { + qWarning() << "Import failed. Cause: " << zip.getZipError(); + return ""; + } + + if(!file.atEnd()) + { + qWarning() << "Import failed. Cause: read all but not EOF"; + return ""; + } + + file.close(); + + if(file.getZipError()!=UNZ_OK) + { + qWarning() << "Import failed. Cause: file.close(): " << file.getZipError(); + return ""; + } + + } + + zip.close(); + + if(zip.getZipError()!=UNZ_OK) + { + qWarning() << "Import failed. Cause: zip.close(): " << zip.getZipError(); + return ""; + } + + + return documentRootFolder; +} + + +UBDocumentProxy* 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); + if (documentRootFolder.isEmpty()) + documentRootFolder = pFile.fileName(); + else + documentRootFolder = path.append("\\content.xml"); + + if(!documentRootFolder.length()){ + UBApplication::showMessage(tr("Import of file %1 failed.").arg(fi.baseName())); + return 0; + } + else{ + //TODO convert expanded CFF file content to ubz destination folder + QString temporaryFolder = QDir::tempPath(); + UBCFFSubsetAdaptor::ConvertCFFFileToUbz(documentRootFolder, temporaryFolder); + // create document proxy for destination folder and return + UBDocumentProxy* newDocument = UBPersistenceManager::persistenceManager()->createDocumentFromDir(temporaryFolder); + UBApplication::showMessage(tr("Import successful.")); + return newDocument; + } +} diff --git a/src/adaptors/UBImportCFF.h b/src/adaptors/UBImportCFF.h new file mode 100644 index 00000000..a7de5414 --- /dev/null +++ b/src/adaptors/UBImportCFF.h @@ -0,0 +1,30 @@ +#ifndef UBIMPORTCFF_H +#define UBIMPORTCFF_H + +#include +#include "UBImportAdaptor.h" + +class UBDocumentProxy; + +class UBImportCFF : public UBImportAdaptor +{ + Q_OBJECT; + + public: + UBImportCFF(QObject *parent = 0); + virtual ~UBImportCFF(); + + virtual QStringList supportedExtentions(); + virtual QString importFileFilter(); + + virtual bool addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile); + + //base class method override + virtual UBDocumentProxy* importFile(const QFile& pFile, const QString& pGroup); + + private: + + virtual QString expandFileToDir(const QFile& pZipFile, const QString& pDir); +}; + +#endif // UBIMPORTCFF_H diff --git a/src/core/UBDocumentManager.cpp b/src/core/UBDocumentManager.cpp index 68afcbd9..8e51a1f6 100644 --- a/src/core/UBDocumentManager.cpp +++ b/src/core/UBDocumentManager.cpp @@ -17,6 +17,7 @@ #include "adaptors/UBImportDocument.h" #include "adaptors/UBImportPDF.h" #include "adaptors/UBImportImage.h" +#include "adaptors/UBImportCFF.h" #include "domain/UBGraphicsScene.h" #include "domain/UBGraphicsSvgItem.h" @@ -67,6 +68,8 @@ UBDocumentManager::UBDocumentManager(QObject *parent) mImportAdaptors.append(pdfImport); UBImportImage* imageImport = new UBImportImage(this); mImportAdaptors.append(imageImport); + UBImportCFF* cffImport = new UBImportCFF(this); + mImportAdaptors.append(cffImport); } From d86e3c01710175f44679ea9969d90adff4c56f67 Mon Sep 17 00:00:00 2001 From: "ivan.ilyin" Date: Fri, 5 Aug 2011 14:07:00 +0300 Subject: [PATCH 2/4] Added initial sources for sff files import. --- src/adaptors/UBCFFSubsetAdaptor.cpp | 598 +++++++++++++++++++++++++++- src/adaptors/UBCFFSubsetAdaptor.h | 63 ++- src/adaptors/UBImportCFF.cpp | 141 +++++-- src/adaptors/adaptors.pri | 114 +++--- 4 files changed, 822 insertions(+), 94 deletions(-) diff --git a/src/adaptors/UBCFFSubsetAdaptor.cpp b/src/adaptors/UBCFFSubsetAdaptor.cpp index a06b26fa..7a62d39c 100644 --- a/src/adaptors/UBCFFSubsetAdaptor.cpp +++ b/src/adaptors/UBCFFSubsetAdaptor.cpp @@ -1,22 +1,610 @@ +#include +#include +#include + #include "UBCFFSubsetAdaptor.h" + + +#include "core/UBPersistenceManager.h" #include "document/UBDocumentProxy.h" +#include "domain/UBItem.h" +#include "domain/UBGraphicsPolygonItem.h" +#include "domain/UBGraphicsStroke.h" + +#include "UBMetadataDcSubsetAdaptor.h" +#include "UBThumbnailAdaptor.h" +#include "UBSvgSubsetAdaptor.h" + +//enum of xmlparse status + +//tag names definition +//use them everiwhere! +static char* tElement = "element"; +static char* tEllipse = "ellipse"; +static char* tIwb = "iwb"; +static char* tMeta = "meta"; +static char* tPage = "page"; +static char* tPageset = "pageset"; +static char* tPolygon = "polygon"; +static char* tRect = "rect"; +static char* tSvg = "svg"; +static char* tTextarea = "textarea"; + +//attribute names definition +static char* aFill = "fill"; +static char* aFillopacity = "fill-opacity"; +static char* aX = "x"; +static char* aY = "y"; +static char* aWidth = "width"; +static char* aHeight = "height"; +static char* aStroke = "stroke"; +static char* aStrokewidth = "stroke-width"; +static char* aCx = "cx"; +static char* aCy = "cy"; +static char* aRx = "rx"; +static char* aRy = "ry"; +static char* aTransform = "transform"; +static char* aViewbox = "viewbox"; UBCFFSubsetAdaptor::UBCFFSubsetAdaptor() { } -void UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFolder, QString &destinationFolder) +bool UBCFFSubsetAdaptor::ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentProxy* pDocument) { - //TODO create document proxy for destination file - // create document proxy with destination folder + //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; + } + + QByteArray data = file.readAll(); + if (data.length() == 0) + { + qWarning() << "Either content file " << cffSourceFile << " is empty or failed to read from file"; + file.close(); + return false; + } + + UBCFFSubsetReader cffReader(pDocument, data); + bool result = cffReader.parse(); + file.close(); + + return result; } -UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy): - mReader(), mProxy(proxy) +UBCFFSubsetAdaptor::UBCFFSubsetReader::UBCFFSubsetReader(UBDocumentProxy *proxy, QByteArray &content): + mReader(content), mProxy(proxy), currentState(NONE) { //TODO parse } + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parse() +{ + UBMetadataDcSubsetAdaptor::persist(mProxy); + + mIndent = ""; + if (!getTempFileName()) + return false; + + bool result = parseDoc(); + if (result) + result = mProxy->pageCount() != 0; + + if (QFile::exists(mTempFilePath)) + QFile::remove(mTempFilePath); + + return result; +} + +int UBCFFSubsetAdaptor::UBCFFSubsetReader::PopState() +{ + if (stateStack.count() == 0) + currentState = NONE; + else + currentState = stateStack.pop(); + + return currentState; +} + +void UBCFFSubsetAdaptor::UBCFFSubsetReader::PushState(int state) +{ + if (currentState != NONE) + stateStack.push(currentState); + currentState = state; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseDoc() +{ + while (!mReader.atEnd()) + { + mReader.readNext(); + if (mReader.isStartElement()) + { + if (!parseCurrentElementStart()) + return false; + } + else + if (mReader.isCharacters()) + { + if (!parseCurrentElementCharacters()) + return false; + } + else + if (mReader.isEndElement()) + { + if (!parseCurrentElementEnd()) + return false; + } + } + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseCurrentElementStart() +{ + QStringRef elName = mReader.name(); + QString log = QString("%1<%2>").arg(mIndent).arg(elName.toString()); + qDebug() << log; + mIndent += " "; + if ( elName == tIwb) + { + if (!parseIwb()) + return false; + + PushState(IWB); + } + else + if ( elName == tMeta) + { + if (!parseIwbMeta()) + return false; + } + else + if ( elName == tSvg) + { + if (!parseSvg()) + return false; + + PushState(SVG); + } + else + if ( elName == tRect) + { + if (!parseRect()) + return false; + } + else + if ( elName == tEllipse) + { + if (!parseEllipse()) + return false; + } + else + if ( elName == tTextarea) + { + if (!parseTextArea()) + return false; + } + else + if ( elName == tPolygon) + { + if (!parsePolygon()) + return false; + } + else + if ( elName == tPage) + { + if (!parsePage()) + return false; + + PushState(PAGE); + } + else + if ( elName == tPageset) + { + if (!parsePageSet()) + return false; + + PushState(PAGESET); + } + else + if ( elName == tElement) + { + if (!parseIwbElementRef()) + return false; + } + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseCurrentElementCharacters() +{ + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseCurrentElementEnd() +{ + QStringRef elName = mReader.name(); + mIndent.remove(0,1); + QString log = QString("%1").arg(mIndent).arg(elName.toString()); + qDebug() << log; + + if ( elName == tIwb) + PopState(); + else + if ( elName == tMeta) + { + } + else + if ( elName == tSvg) + { + persistCurrentScene(); + PopState(); + } + else + if ( elName == tPage) + { + persistCurrentScene(); + PopState(); + } + else + if ( elName == tPageset) + { + PopState(); + } + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwb() +{ + if (!stateStack.empty() || currentState != NONE) + { + qWarning() << "iwb content parse error, unexpected iwb tag at line" << mReader.lineNumber(); + return false; + } + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbMeta() +{ + if (currentState != IWB) + { + qWarning() << "iwb content parse error, unexpected meta tag at line" << mReader.lineNumber(); + return false; + } + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseSvg() +{ + if (currentState != IWB) + { + qWarning() << "iwb content parse error, unexpected svg tag at line" << mReader.lineNumber(); + return false; + } + + getViewBoxDimenstions(mReader.attributes().value(aViewbox).toString()); + mSize = QSize(mReader.attributes().value(aWidth).toString().toInt(), + mReader.attributes().value(aHeight).toString().toInt()); + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseRect() +{ + if (currentState != SVG && currentState != PAGE) + { + qWarning() << "iwb content parse error, unexpected rect tag at line" << mReader.lineNumber(); + return false; + } + + //create new scene if it's not created yet (for one page document case) + if (currentState == SVG && mCurrentScene == NULL) + createNewScene(); + + //fill and stroke color + QColor fillColor = colorFromString(mReader.attributes().value(aFill).toString()); + QColor strokeColor = colorFromString(mReader.attributes().value(aStroke).toString()); + int strokeWidth = mReader.attributes().value(aStrokewidth).toString().toInt(); + + //rect lef top corner coordinates + qreal x1 = mReader.attributes().value(aX).toString().toDouble(); + qreal y1 = mReader.attributes().value(aY).toString().toDouble(); + //rect dimensions + qreal width = mReader.attributes().value(aWidth).toString().toDouble(); + qreal height = mReader.attributes().value(aHeight).toString().toDouble(); + + //init svg generator with temp file + QSvgGenerator *generator = createSvgGenerator(); + + //init painter to paint to svg + QPainter painter; + painter.begin(generator); + + //check if rect is rotated + if (mReader.attributes().hasAttribute(aTransform)) + { + QTransform transform = transformFromString(mReader.attributes().value(aTransform).toString()); + painter.setTransform(transform); + //change left top coordinates to correspond to transformation + x1 -= transform.dx(); + y1 -= transform.dy(); + } + + painter.setBrush(QBrush(fillColor)); + painter.fillRect(x1, y1, width, height, fillColor); + + QPen pen(strokeColor); + pen.setWidth(strokeWidth); + painter.setPen(pen); + painter.drawRect(x1, y1, width, height); + + painter.end(); + + //add resulting svg file to scene + mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName())); + delete generator; + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseEllipse() +{ + if (currentState != SVG && currentState != PAGE) + { + qWarning() << "iwb content parse error, unexpected ellipse tag at line" << mReader.lineNumber(); + return false; + } + + //create new scene if it's not created yet (for one page document case) + if (currentState == SVG && mCurrentScene == NULL) + createNewScene(); + + QSvgGenerator *generator = createSvgGenerator(); + + //fill and stroke color + QColor fillColor = colorFromString(mReader.attributes().value(aFill).toString()); + QColor strokeColor = colorFromString(mReader.attributes().value(aStroke).toString()); + int strokeWidth = mReader.attributes().value(aStrokewidth).toString().toInt(); + + //ellipse center coordinates + qreal cx = mReader.attributes().value(aCx).toString().toDouble(); + qreal cy = mReader.attributes().value(aCy).toString().toDouble(); + //ellipse horisontal and vertical radius + qreal rx = mReader.attributes().value(aRx).toString().toDouble(); + qreal ry = mReader.attributes().value(aRy).toString().toDouble(); + + //we should change cx and cy by rx and ry because qpainter + //draws ellipse by its rect coordinates + cx -= rx; + cy -= ry; + + //init painter to paint to svg + QPainter painter; + painter.begin(generator); + + //check if ellipse is rotated + if (mReader.attributes().hasAttribute(aTransform)) + { + QTransform transform = transformFromString(mReader.attributes().value(aTransform).toString()); + painter.setTransform(transform); + //change cx and cy to correspond to transformation + cx -= transform.dx(); + cy -= transform.dy(); + } + + QPen pen(strokeColor); + pen.setWidth(strokeWidth); + painter.setPen(pen); + painter.setBrush(QBrush(fillColor)); + + painter.drawEllipse(cx, cy, rx * 2, ry * 2); + + painter.end(); + + //add resulting svg file to scene + mCurrentScene->addSvg(QUrl::fromLocalFile(generator->fileName())); + delete generator; + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseTextArea() +{ + if (currentState != SVG && currentState != PAGE) + { + qWarning() << "iwb content parse error, unexpected textarea tag at line" << mReader.lineNumber(); + return false; + } + + //create new scene if it's not created yet (for one page document case) + if (currentState == SVG && mCurrentScene == NULL) + createNewScene(); + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePolygon() +{ + if (currentState != SVG && currentState != PAGE) + { + qWarning() << "iwb content parse error, unexpected polygon tag at line" << mReader.lineNumber(); + return false; + } + + //create new scene if it's not created yet (for one page document case) + if (currentState == SVG && mCurrentScene == NULL) + createNewScene(); + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePage() +{ + if (currentState != PAGESET && currentState != SVG) + { + qWarning() << "iwb content parse error, unexpected page tag at line" << mReader.lineNumber(); + return false; + } + + createNewScene(); + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parsePageSet() +{ + if (currentState != SVG) + { + qWarning() << "iwb content parse error, unexpected page tag at line" << mReader.lineNumber(); + return false; + } + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::parseIwbElementRef() +{ + if (currentState != IWB) + { + qWarning() << "iwb content parse error, unexpected element tag at line" << mReader.lineNumber(); + return false; + } + + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::createNewScene() +{ + mCurrentScene = UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mProxy, mProxy->pageCount()); + return true; +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::persistCurrentScene() +{ + if (mCurrentScene != 0 && mCurrentScene->isModified()) + { + UBThumbnailAdaptor::persistScene(mProxy->persistencePath(), mCurrentScene, mProxy->pageCount() - 1); + UBSvgSubsetAdaptor::persistScene(mProxy, mCurrentScene, mProxy->pageCount() - 1); + + mCurrentScene->setModified(false); + mCurrentScene = 0; + } + 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) +{ + //check pattern for strings like 'rotate(10)' + QRegExp regexp("rotate\\(([-+]{0,1}[0-9]*\\.{0,1}[0-9]*)\\)"); + if (regexp.exactMatch(trString)) + { + if (regexp.capturedTexts().count() == 2 && regexp.capturedTexts().at(0).length() == trString.length()) + { + qreal angle = regexp.capturedTexts().at(1).toDouble(); + return QTransform().rotate(angle); + } + } + + //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(trString)) + { + if (regexp.capturedTexts().count() == 4 && regexp.capturedTexts().at(0).length() == trString.length()) + { + qreal angle = regexp.capturedTexts().at(1).toDouble(); + qreal dx = regexp.capturedTexts().at(2).toDouble(); + qreal dy = regexp.capturedTexts().at(3).toDouble(); + return QTransform().translate(dx, dy).rotate(angle); + } + } + + return QTransform(); +} + +bool UBCFFSubsetAdaptor::UBCFFSubsetReader::getViewBoxDimenstions(const QString& viewBox) +{ + //check pattern for strings like 'rotate(10)' + QRegExp regexp("([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)"); + if (regexp.exactMatch(viewBox)) + { + int capturesCount = regexp.capturedTexts().count(); + if (capturesCount == 5 && regexp.capturedTexts().at(0).length() == viewBox.length()) + { + mViewBox = QRectF(0, 0, regexp.capturedTexts().at(3).toDouble(), regexp.capturedTexts().at(4).toDouble()); + return true; + } + } + + mViewBox = QRectF(0, 0, 1000, 1000); + return false; +} + +QSvgGenerator* UBCFFSubsetAdaptor::UBCFFSubsetReader::createSvgGenerator() +{ + QSvgGenerator* generator = new QSvgGenerator(); + generator->setFileName(mTempFilePath); + generator->setSize(mSize); + generator->setViewBox(mViewBox); + + 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; + } + } + +} diff --git a/src/adaptors/UBCFFSubsetAdaptor.h b/src/adaptors/UBCFFSubsetAdaptor.h index 34db3d80..ac3d6142 100644 --- a/src/adaptors/UBCFFSubsetAdaptor.h +++ b/src/adaptors/UBCFFSubsetAdaptor.h @@ -3,24 +3,83 @@ #include #include +#include class UBDocumentProxy; +class UBGraphicsScene; +class QSvgGenerator; class UBCFFSubsetAdaptor { public: UBCFFSubsetAdaptor(); - static void ConvertCFFFileToUbz(QString &cffSourceFolder, QString &destinationFolder); + static bool ConvertCFFFileToUbz(QString &cffSourceFile, UBDocumentProxy* pDocument); private: class UBCFFSubsetReader { + //xml parse states definition + enum + { + NONE, + IWB, + SVG, + PAGESET, + PAGE, + TEXTAREA, + TSPAN + }; + public: - UBCFFSubsetReader(UBDocumentProxy *proxy); + UBCFFSubsetReader(UBDocumentProxy *proxy, QByteArray &content); QXmlStreamReader mReader; UBDocumentProxy *mProxy; + + bool parse(); + + private: + QString mTempFilePath; + UBGraphicsScene *mCurrentScene; + QString mIndent; + QRectF mViewBox; + QSize mSize; + + //methods to store current xml parse state + int PopState(); + void PushState(int state); + + //elements parsing methods + bool parseDoc(); + + bool parseCurrentElementStart(); + bool parseCurrentElementCharacters(); + bool parseCurrentElementEnd(); + + bool parseIwb(); + bool parseIwbMeta(); + bool parseSvg(); + bool parseRect(); + bool parseEllipse(); + bool parseTextArea(); + bool parsePolygon(); + bool parsePage(); + bool parsePageSet(); + bool parseIwbElementRef(); + + bool createNewScene(); + bool persistCurrentScene(); + + QStack stateStack; + int currentState; + + //helper methods + QColor colorFromString(const QString& clrString); + QTransform transformFromString(const QString trString); + bool getViewBoxDimenstions(const QString& viewBox); + QSvgGenerator* createSvgGenerator(); + bool getTempFileName(); }; }; diff --git a/src/adaptors/UBImportCFF.cpp b/src/adaptors/UBImportCFF.cpp index 5487a0d5..c79f316b 100644 --- a/src/adaptors/UBImportCFF.cpp +++ b/src/adaptors/UBImportCFF.cpp @@ -5,14 +5,15 @@ #include "core/UBApplication.h" #include "core/UBPersistenceManager.h" #include "core/UBDocumentManager.h" +#include "core/memcheck.h" +#include "core/UBPersistenceManager.h" + +#include "frameworks/UBFileSystemUtils.h" #include "domain/UBGraphicsPDFItem.h" #include "pdf/PDFRenderer.h" -#include "core/memcheck.h" - -#include "core/UBPersistenceManager.h" #include "UBCFFSubsetAdaptor.h" @@ -63,25 +64,53 @@ QString UBImportCFF::importFileFilter() bool UBImportCFF::addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile) { - //TODO add cff file import here -/* int res = UBDocumentManager::documentManager()->addImageAsPageToDocument(QStringList(QFileInfo(pFile).absoluteFilePath()), pDocument); - if (res == 0) - { - UBApplication::showMessage(tr("Image import failed.")); - return false; + 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; + } } - else - { - UBApplication::showMessage(tr("Image import successful.")); - return true; - }*/ - return true; } QString UBImportCFF::expandFileToDir(const QFile& pZipFile, const QString& pDir) { - - QDir rootDir(pDir); QuaZip zip(pZipFile.fileName()); if(!zip.open(QuaZip::mdUnzip)) @@ -94,10 +123,34 @@ QString UBImportCFF::expandFileToDir(const QFile& pZipFile, const QString& pDir) QuaZipFileInfo info; QuaZipFile file(&zip); - // TODO UB 4.x implement a mechanism that can replace an existing - // document based on the UID of the document. - bool createNewDocument = true; + //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"; + } // first we search the metadata.rdf to check the document properties for(bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) @@ -111,9 +164,6 @@ QString UBImportCFF::expandFileToDir(const QFile& pZipFile, const QString& pDir) QFileInfo currentFileInfo(pDir + "/" + file.getActualFileName()); } - if (createNewDocument) - documentRootFolder = UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath(); - QFile out; char c; @@ -208,22 +258,49 @@ UBDocumentProxy* UBImportCFF::importFile(const QFile& pFile, const QString& pGro QString path = QDir::tempPath(); QString documentRootFolder = expandFileToDir(pFile, path); + QString contentFile; if (documentRootFolder.isEmpty()) - documentRootFolder = pFile.fileName(); + //if file has failed to umzip it is probably just xml file + contentFile = pFile.fileName(); else - documentRootFolder = path.append("\\content.xml"); + //get path to content xml + contentFile = QString("%1/content.xml").arg(documentRootFolder); - if(!documentRootFolder.length()){ + if(!contentFile.length()){ UBApplication::showMessage(tr("Import of file %1 failed.").arg(fi.baseName())); return 0; } else{ - //TODO convert expanded CFF file content to ubz destination folder - QString temporaryFolder = QDir::tempPath(); - UBCFFSubsetAdaptor::ConvertCFFFileToUbz(documentRootFolder, temporaryFolder); - // create document proxy for destination folder and return - UBDocumentProxy* newDocument = UBPersistenceManager::persistenceManager()->createDocumentFromDir(temporaryFolder); - UBApplication::showMessage(tr("Import successful.")); + //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; } } + diff --git a/src/adaptors/adaptors.pri b/src/adaptors/adaptors.pri index 8404364d..7dd7104e 100644 --- a/src/adaptors/adaptors.pri +++ b/src/adaptors/adaptors.pri @@ -1,55 +1,59 @@ - -HEADERS += src/adaptors/UBExportAdaptor.h\ - src/adaptors/UBExportPDF.h \ - src/adaptors/UBExportFullPDF.h \ - src/adaptors/UBExportDocument.h \ - src/adaptors/UBSvgSubsetAdaptor.h \ - src/adaptors/UBMetadataDcSubsetAdaptor.h \ - src/adaptors/UBImportAdaptor.h \ - src/adaptors/UBImportDocument.h \ - src/adaptors/UBThumbnailAdaptor.h \ - src/adaptors/UBImportPDF.h \ - src/adaptors/UBImportImage.h \ - src/adaptors/UBIniFileParser.h \ - src/adaptors/UBExportWeb.h \ - src/adaptors/UBWebPublisher.h - -HEADERS += src/adaptors/publishing/UBDocumentPublisher.h \ - src/adaptors/publishing/UBCapturePublisher.h \ - src/adaptors/publishing/UBAbstractPublisher.h \ - src/adaptors/publishing/UBSvgSubsetRasterizer.h - -HEADERS += src/adaptors/voting/UBAbstractVotingSystem.h - - -SOURCES += src/adaptors/UBExportAdaptor.cpp\ - src/adaptors/UBExportPDF.cpp \ - src/adaptors/UBExportFullPDF.cpp \ - src/adaptors/UBExportDocument.cpp \ - src/adaptors/UBSvgSubsetAdaptor.cpp \ - src/adaptors/UBMetadataDcSubsetAdaptor.cpp \ - src/adaptors/UBImportAdaptor.cpp \ - src/adaptors/UBImportDocument.cpp \ - src/adaptors/UBThumbnailAdaptor.cpp \ - src/adaptors/UBImportPDF.cpp \ - src/adaptors/UBImportImage.cpp \ - src/adaptors/UBIniFileParser.cpp \ - src/adaptors/UBExportWeb.cpp \ - src/adaptors/UBWebPublisher.cpp - -SOURCES += src/adaptors/publishing/UBDocumentPublisher.cpp \ - src/adaptors/publishing/UBCapturePublisher.cpp \ - src/adaptors/publishing/UBAbstractPublisher.cpp \ - src/adaptors/publishing/UBSvgSubsetRasterizer.cpp - -SOURCES += src/adaptors/voting/UBAbstractVotingSystem.cpp - - -win32 { - - SOURCES += src/adaptors/voting/UBReply2005VotingSystem.cpp \ - src/adaptors/voting/UBReplyWRS970VotingSystem.cpp - - HEADERS += src/adaptors/voting/UBReply2005VotingSystem.h \ - src/adaptors/voting/UBReplyWRS970VotingSystem.h -} + +HEADERS += src/adaptors/UBExportAdaptor.h\ + src/adaptors/UBExportPDF.h \ + src/adaptors/UBExportFullPDF.h \ + src/adaptors/UBExportDocument.h \ + src/adaptors/UBSvgSubsetAdaptor.h \ + src/adaptors/UBMetadataDcSubsetAdaptor.h \ + src/adaptors/UBImportAdaptor.h \ + src/adaptors/UBImportDocument.h \ + src/adaptors/UBThumbnailAdaptor.h \ + src/adaptors/UBImportPDF.h \ + src/adaptors/UBImportImage.h \ + src/adaptors/UBIniFileParser.h \ + src/adaptors/UBExportWeb.h \ + src/adaptors/UBWebPublisher.h \ + src/adaptors/UBImportCFF.h \ + src/adaptors/UBCFFSubsetAdaptor.h + +HEADERS += src/adaptors/publishing/UBDocumentPublisher.h \ + src/adaptors/publishing/UBCapturePublisher.h \ + src/adaptors/publishing/UBAbstractPublisher.h \ + src/adaptors/publishing/UBSvgSubsetRasterizer.h + +HEADERS += src/adaptors/voting/UBAbstractVotingSystem.h + + +SOURCES += src/adaptors/UBExportAdaptor.cpp\ + src/adaptors/UBExportPDF.cpp \ + src/adaptors/UBExportFullPDF.cpp \ + src/adaptors/UBExportDocument.cpp \ + src/adaptors/UBSvgSubsetAdaptor.cpp \ + src/adaptors/UBMetadataDcSubsetAdaptor.cpp \ + src/adaptors/UBImportAdaptor.cpp \ + src/adaptors/UBImportDocument.cpp \ + src/adaptors/UBThumbnailAdaptor.cpp \ + src/adaptors/UBImportPDF.cpp \ + src/adaptors/UBImportImage.cpp \ + src/adaptors/UBIniFileParser.cpp \ + src/adaptors/UBExportWeb.cpp \ + src/adaptors/UBWebPublisher.cpp \ + src/adaptors/UBImportCFF.cpp \ + src/adaptors/UBCFFSubsetAdaptor.cpp + +SOURCES += src/adaptors/publishing/UBDocumentPublisher.cpp \ + src/adaptors/publishing/UBCapturePublisher.cpp \ + src/adaptors/publishing/UBAbstractPublisher.cpp \ + src/adaptors/publishing/UBSvgSubsetRasterizer.cpp + +SOURCES += src/adaptors/voting/UBAbstractVotingSystem.cpp + + +win32 { + + SOURCES += src/adaptors/voting/UBReply2005VotingSystem.cpp \ + src/adaptors/voting/UBReplyWRS970VotingSystem.cpp + + HEADERS += src/adaptors/voting/UBReply2005VotingSystem.h \ + src/adaptors/voting/UBReplyWRS970VotingSystem.h +} From 6c0ce973592149a13109825a749a9feed6151e6d Mon Sep 17 00:00:00 2001 From: Claudio Valerio Date: Mon, 8 Aug 2011 08:32:36 +0200 Subject: [PATCH 3/4] Update min version --- Sankore_3.1.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sankore_3.1.pro b/Sankore_3.1.pro index 7003f481..e6a69f4e 100644 --- a/Sankore_3.1.pro +++ b/Sankore_3.1.pro @@ -7,9 +7,9 @@ CONFIG += debug_and_release \ no_include_pwd VERSION_MAJ = 1 -VERSION_MIN = 10 +VERSION_MIN = 11 VERSION_TYPE = b # a = alpha, b = beta, r = release, other => error -VERSION_PATCH = 01 +VERSION_PATCH = 00 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_TYPE}.$${VERSION_PATCH}" VERSION = $$replace(VERSION, "\\.r", "") From 782a518c6a690f4d81c17d10a59a95fc82b79fc0 Mon Sep 17 00:00:00 2001 From: Claudio Valerio Date: Mon, 8 Aug 2011 08:44:01 +0200 Subject: [PATCH 4/4] Removed unused code --- src/core/UBApplication.cpp | 5 ----- src/core/UBPreferencesController.cpp | 1 - 2 files changed, 6 deletions(-) diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index bddfc5c3..b1942ce1 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -268,11 +268,6 @@ int UBApplication::exec(const QString& pFileToImport) connect(mainWindow->actionCopy, SIGNAL(triggered()), applicationController, SLOT(actionCopy())); connect(mainWindow->actionPaste, SIGNAL(triggered()), applicationController, SLOT(actionPaste())); -//#ifndef __ppc__ -// // this cause a problem on MACX/PPC (see https://trac.assembla.com/uniboard/ticket/862) -// installEventFilter(new UBIdleTimer(this)); -//#endif - applicationController->initScreenLayout(); boardController->setupLayout(); diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 867f3064..e84c6031 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -65,7 +65,6 @@ UBPreferencesController::UBPreferencesController(QWidget *parent) , mMarkerProperties(0) { mPreferencesWindow = new UBPreferencesDialog(this,parent, Qt::Dialog); - // mPreferencesWindow = new QDialog(parent, Qt::Dialog); mPreferencesUI = new Ui::preferencesDialog(); // deleted in mPreferencesUI->setupUi(mPreferencesWindow); connect(mPreferencesUI->Username_textBox, SIGNAL(editingFinished()), this, SLOT(onCommunityUsernameChanged()));