First step of OpenSankore Document Mode integration

preferencesAboutTextFull
Clément Fauconnier 7 years ago
parent bb60925bdd
commit 8ecf99f838
  1. 8
      OpenBoard.pro
  2. 69
      plugins/cffadaptor/UBCFFAdaptor.pro
  3. 5
      plugins/cffadaptor/postScript_mac.sh
  4. 9
      plugins/cffadaptor/resources/images/soundOn.svg
  5. 5
      plugins/cffadaptor/resources/resources.qrc
  6. 2069
      plugins/cffadaptor/src/UBCFFAdaptor.cpp
  7. 175
      plugins/cffadaptor/src/UBCFFAdaptor.h
  8. 34
      plugins/cffadaptor/src/UBCFFAdaptor_global.h
  9. 405
      plugins/cffadaptor/src/UBCFFConstants.h
  10. 69
      plugins/cffadaptor/src/UBGlobals.h
  11. 6
      plugins/plugins.pri
  12. 2
      resources/OpenBoard.qrc
  13. 209
      resources/forms/documents.ui
  14. 132
      resources/forms/webPublishing.ui
  15. BIN
      resources/images/collapse-all.png
  16. BIN
      resources/images/expand-all.png
  17. 1549
      src/adaptors/UBCFFSubsetAdaptor.cpp
  18. 153
      src/adaptors/UBCFFSubsetAdaptor.h
  19. 6
      src/adaptors/UBExportAdaptor.h
  20. 99
      src/adaptors/UBExportCFF.cpp
  21. 49
      src/adaptors/UBExportCFF.h
  22. 198
      src/adaptors/UBExportDocumentSetAdaptor.cpp
  23. 60
      src/adaptors/UBExportDocumentSetAdaptor.h
  24. 11
      src/adaptors/UBExportFullPDF.cpp
  25. 1
      src/adaptors/UBExportFullPDF.h
  26. 11
      src/adaptors/UBExportPDF.cpp
  27. 1
      src/adaptors/UBExportPDF.h
  28. 294
      src/adaptors/UBImportCFF.cpp
  29. 50
      src/adaptors/UBImportCFF.h
  30. 205
      src/adaptors/UBImportDocumentSetAdaptor.cpp
  31. 52
      src/adaptors/UBImportDocumentSetAdaptor.h
  32. 76
      src/adaptors/UBWebPublisher.cpp
  33. 53
      src/adaptors/UBWebPublisher.h
  34. 16
      src/adaptors/adaptors.pri
  35. 658
      src/adaptors/publishing/UBDocumentPublisher.cpp
  36. 84
      src/adaptors/publishing/UBDocumentPublisher.h
  37. 18
      src/adaptors/publishing/UBSvgSubsetRasterizer.cpp
  38. 18
      src/adaptors/publishing/UBSvgSubsetRasterizer.h
  39. 3
      src/board/UBBoardController.cpp
  40. 2
      src/board/UBBoardController.h
  41. 7
      src/core/UBApplicationController.cpp
  42. 95
      src/core/UBDocumentManager.cpp
  43. 7
      src/core/UBDocumentManager.h
  44. 628
      src/core/UBForeignObjectsHandler.cpp
  45. 49
      src/core/UBForeignObjectsHandler.h
  46. 760
      src/core/UBPersistenceManager.cpp
  47. 130
      src/core/UBPersistenceManager.h
  48. 27
      src/core/UBSceneCache.cpp
  49. 2
      src/core/UBSceneCache.h
  50. 6
      src/core/core.pri
  51. 90
      src/customWidgets/UBActionableWidget.cpp
  52. 68
      src/customWidgets/UBActionableWidget.h
  53. 212
      src/customWidgets/UBGraphicsItemAction.cpp
  54. 124
      src/customWidgets/UBGraphicsItemAction.h
  55. 368
      src/customWidgets/UBMediaWidget.cpp
  56. 133
      src/customWidgets/UBMediaWidget.h
  57. 10
      src/customWidgets/customWidgets.pri
  58. 8
      src/document/UBDocumentContainer.cpp
  59. 4
      src/document/UBDocumentContainer.h
  60. 3744
      src/document/UBDocumentController.cpp
  61. 444
      src/document/UBDocumentController.h
  62. 13
      src/document/UBDocumentProxy.cpp
  63. 2
      src/document/UBDocumentProxy.h
  64. 25
      src/document/UBSortFilterProxyModel.cpp
  65. 15
      src/document/UBSortFilterProxyModel.h
  66. 13
      src/document/document.pri
  67. 4
      src/gui/gui.pri

@ -65,6 +65,11 @@ DEPENDPATH += src/pdf-merger
INCLUDEPATH += src/pdf-merger
include(src/pdf-merger/pdfMerger.pri)
#plugins
include(plugins/plugins.pri)
INCLUDEPATH += plugins/cffadaptor/src
#ThirdParty
DEPENDPATH += $$THIRD_PARTY_PATH/quazip/
INCLUDEPATH += $$THIRD_PARTY_PATH/quazip/
@ -82,7 +87,8 @@ FORMS += resources/forms/mainWindow.ui \
resources/forms/trapFlash.ui \
resources/forms/youTubePublishingDialog.ui \
resources/forms/capturePublishing.ui \
resources/forms/intranetPodcastPublishingDialog.ui
resources/forms/intranetPodcastPublishingDialog.ui \
resources/forms/webPublishing.ui
UB_ETC.files = resources/etc
UB_I18N.files = resources/i18n/*.qm

@ -0,0 +1,69 @@
#-------------------------------------------------
#
# 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

@ -0,0 +1,5 @@
#!/bin/bash
SOURCE=$1
DESTINATION=$2
mkdir -p $DESTINATION
cp -R $SOURCE/ $DESTINATION

@ -0,0 +1,9 @@
<?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>

After

Width:  |  Height:  |  Size: 572 B

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>images/soundOn.svg</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,175 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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

@ -0,0 +1,34 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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

@ -0,0 +1,405 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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 ubNS = "http://uniboard.mnemis.com/document";
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 ubNSPrefix = "ub";
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

@ -0,0 +1,69 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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

@ -0,0 +1,6 @@
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

@ -360,5 +360,7 @@
<file>images/ungroupItems.svg</file>
<file>images/setAsBackground.svg</file>
<file>images/backgroundPalette/resetDefaultGridSize.svg</file>
<file>images/collapse-all.png</file>
<file>images/expand-all.png</file>
</qresource>
</RCC>

@ -28,50 +28,142 @@
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="topFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QWidget" name="topWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QFrame" name="topLeftFrame">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="opaqueResize">
<bool>true</bool>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<widget class="QWidget" name="topLeftWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Panel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="UBDocumentTreeWidget" name="documentTreeWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="collapseAll">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Collapse All</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../OpenBoard.qrc">
<normaloff>:/images/collapse-all.png</normaloff>:/images/collapse-all.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="expandAll">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Expand All</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../OpenBoard.qrc">
<normaloff>:/images/expand-all.png</normaloff>:/images/expand-all.png</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="sortKind">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>4</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Select a sort</string>
</property>
</item>
<item>
<property name="text">
<string>Creation date</string>
</property>
</item>
<item>
<property name="text">
<string>Update date</string>
</property>
</item>
<item>
<property name="text">
<string>Alphabetical order</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="sortOrder">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Ascending order</string>
</property>
</item>
<item>
<property name="text">
<string>Descending order</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="UBDocumentTreeView" name="documentTreeView">
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
@ -79,14 +171,23 @@
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="autoScrollMargin">
<number>65</number>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="autoExpandDelay">
<number>2</number>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerItem</enum>
</property>
<property name="animated">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
@ -94,25 +195,15 @@
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="topRightFrame" native="true">
<widget class="QFrame" name="topRightFrame">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="UBDocumentThumbnailWidget" name="thumbnailWidget">
<property name="contextMenuPolicy">
@ -147,7 +238,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -224,6 +324,7 @@
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
@ -238,9 +339,9 @@
<header>gui/UBDocumentThumbnailWidget.h</header>
</customwidget>
<customwidget>
<class>UBDocumentTreeWidget</class>
<extends>QTreeWidget</extends>
<header>gui/UBDocumentTreeWidget.h</header>
<class>UBDocumentTreeView</class>
<extends>QTreeView</extends>
<header>document/UBDocumentController.h</header>
</customwidget>
</customwidgets>
<resources>

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>documentPublishingDialog</class>
<widget class="QDialog" name="documentPublishingDialog">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>607</width>
<height>405</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="titleLabel">
<property name="text">
<string>Title</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="title">
<property name="maxLength">
<number>60</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>E-mail</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="email"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Author</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="author"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="decriptionLabel">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPlainTextEdit" name="description">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>168</height>
</size>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="attachPDF">
<property name="text">
<string>Attach Downloadable PDF Version</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="attachUBZ">
<property name="text">
<string>Attach Downloadable Uniboard File (UBZ)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="videoWarning">
<property name="text">
<string>Warning: This documents contains video, which will not be displayed properly on the Web</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QDialogButtonBox" name="dialogButtons">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because it is too large Load Diff

@ -0,0 +1,153 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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

@ -36,7 +36,7 @@ class UBDocumentProxy;
class UBExportAdaptor : public QObject
{
Q_OBJECT;
Q_OBJECT
public:
UBExportAdaptor(QObject *parent = 0);
@ -46,6 +46,9 @@ class UBExportAdaptor : public QObject
virtual QString exportExtention() { return "";}
virtual void persist(UBDocumentProxy* pDocument) = 0;
virtual bool persistsDocument(UBDocumentProxy* pDocument, const QString& filename);
virtual bool associatedActionactionAvailableFor(const QModelIndex &selectedIndex) {Q_UNUSED(selectedIndex); return false;}
QAction *associatedAction() {return mAssociatedAction;}
void setAssociatedAction(QAction *pAssociatedAction) {mAssociatedAction = pAssociatedAction;}
virtual void setVerbose(bool verbose)
{
@ -66,6 +69,7 @@ class UBExportAdaptor : public QObject
void showErrorsList(QList<QString> errorsList);
bool mIsVerbose;
QAction* mAssociatedAction;
};

@ -0,0 +1,99 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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"
#include "document/UBDocumentController.h"
#include <QModelIndex>
#include <QObject>
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)
{
QString src = pDocument->persistencePath();
if (!pDocument)
return;
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();
}
}
bool UBExportCFF::associatedActionactionAvailableFor(const QModelIndex &selectedIndex)
{
const UBDocumentTreeModel *docModel = qobject_cast<const UBDocumentTreeModel*>(selectedIndex.model());
if (!selectedIndex.isValid() || docModel->isCatalog(selectedIndex)) {
return false;
}
return true;
}

@ -0,0 +1,49 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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);
virtual bool associatedActionactionAvailableFor(const QModelIndex &selectedIndex);
};
#endif /* UBExportCFF_H_ */

@ -0,0 +1,198 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBExportDocumentSetAdaptor.h"
#include "UBExportDocument.h"
#include "frameworks/UBPlatformUtils.h"
#include "core/UBDocumentManager.h"
#include "core/UBApplication.h"
#include "document/UBDocumentProxy.h"
#include "document/UBDocumentController.h"
#include "globals/UBGlobals.h"
#include "core/UBPersistenceManager.h"
#include "core/UBForeignObjectsHandler.h"
THIRD_PARTY_WARNINGS_DISABLE
#include "quazip.h"
#include "quazipfile.h"
THIRD_PARTY_WARNINGS_ENABLE
#include "core/memcheck.h"
UBExportDocumentSetAdaptor::UBExportDocumentSetAdaptor(QObject *parent)
: UBExportAdaptor(parent)
{
}
UBExportDocumentSetAdaptor::~UBExportDocumentSetAdaptor()
{
// NOOP
}
void UBExportDocumentSetAdaptor::persist(UBDocumentProxy* pDocumentProxy)
{
QModelIndex treeViewParentIndex;
UBPersistenceManager *persistenceManager = UBPersistenceManager::persistenceManager();
UBDocumentTreeModel *treeModel = persistenceManager->mDocumentTreeStructureModel;
QString filename;
if (pDocumentProxy) {
treeViewParentIndex = treeModel->indexForProxy(pDocumentProxy);
if (!treeViewParentIndex.isValid()) {
qDebug() << "failed to export";
UBApplication::showMessage(tr("Failed to export..."));
return;
}
filename = askForFileName(pDocumentProxy, tr("Export as UBX File"));
} else {
treeViewParentIndex = UBApplication::documentController->firstSelectedTreeIndex();
if (!treeViewParentIndex.isValid()) {
qDebug() << "failed to export";
UBApplication::showMessage(tr("Failed to export..."));
return;
}
UBDocumentTreeNode* node = treeModel->nodeFromIndex(treeViewParentIndex);
UBDocumentProxy proxy;
proxy.setMetaData(UBSettings::documentName,node->displayName());
filename = askForFileName(&proxy, tr("Export as UBX File"));
}
if (filename.length() > 0)
{
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
if (mIsVerbose)
UBApplication::showMessage(tr("Exporting document..."));
if (persistData(treeViewParentIndex, filename)) {
if (mIsVerbose) {
UBApplication::showMessage(tr("Export successful."));
}
} else {
if (mIsVerbose) {
UBApplication::showMessage(tr("Export failed."));
}
}
QApplication::restoreOverrideCursor();
}
}
bool UBExportDocumentSetAdaptor::persistData(const QModelIndex &pRootIndex, QString filename)
{
UBPersistenceManager *persistenceManager = UBPersistenceManager::persistenceManager();
UBDocumentTreeModel *treeModel = persistenceManager->mDocumentTreeStructureModel;
QModelIndex index = pRootIndex;
if (!index.isValid()) {
return false;
}
QuaZip zip(filename);
zip.setFileNameCodec("UTF-8");
if(!zip.open(QuaZip::mdCreate))
{
qWarning("Export failed. Cause: zip.open(): %d", zip.getZipError());
return false;
}
if (!addDocumentToZip(pRootIndex, treeModel, zip)) {
zip.close();
return false;
}
zip.close();
UBPlatformUtils::setFileType(filename, 0x5542647A /* UBdz */);
return true;
}
QString UBExportDocumentSetAdaptor::exportExtention()
{
return QString(".ubx");
}
QString UBExportDocumentSetAdaptor::exportName()
{
return tr("Export to Sankore UBX Format");
}
bool UBExportDocumentSetAdaptor::addDocumentToZip(const QModelIndex &pIndex, UBDocumentTreeModel *model, QuaZip &zip)
{
static int i = 0;
i++;
QModelIndex parentIndex = pIndex;
if (!parentIndex.isValid()) {
return false;
}
UBDocumentProxy *pDocumentProxy = model->proxyForIndex(parentIndex);
if (pDocumentProxy) {
// Q_ASSERT(QFileInfo(pDocumentProxy->persistencePath()).exists());
// UBForeighnObjectsHandler cleaner;
// cleaner.cure(pDocumentProxy->persistencePath());
//UniboardSankoreTransition document;
QString documentPath(pDocumentProxy->persistencePath());
//document.checkDocumentDirectory(documentPath);
QDir documentDir = QDir(pDocumentProxy->persistencePath());
QuaZipFile zipFile(&zip);
UBFileSystemUtils::compressDirInZip(documentDir, QFileInfo(documentPath).fileName() + "/", &zipFile, false);
if(zip.getZipError() != 0)
{
qWarning("Export failed. Cause: zip.close(): %d", zip.getZipError());
}
}
for (int i = 0; i < model->rowCount(parentIndex); ++i) {
QModelIndex curIndex = model->index(i, 0, parentIndex);
if (!addDocumentToZip(curIndex, model, zip)) {
return false;
}
}
return true;
}
bool UBExportDocumentSetAdaptor::associatedActionactionAvailableFor(const QModelIndex &selectedIndex)
{
const UBDocumentTreeModel *docModel = qobject_cast<const UBDocumentTreeModel*>(selectedIndex.model());
if (!selectedIndex.isValid() || docModel->isDocument(selectedIndex)) {
return false;
}
return true;
}

@ -0,0 +1,60 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBEXPORTDOCUMENTSETADAPTOR_H
#define UBEXPORTDOCUMENTSETADAPTOR_H
#include <QtCore>
#include "UBExportAdaptor.h"
#include "frameworks/UBFileSystemUtils.h"
#include "globals/UBGlobals.h"
THIRD_PARTY_WARNINGS_DISABLE
#include "quazip.h"
#include "quazipfile.h"
THIRD_PARTY_WARNINGS_ENABLE
class UBDocumentProxy;
class UBDocumentTreeModel;
class UBExportDocumentSetAdaptor : public UBExportAdaptor
{
Q_OBJECT
public:
UBExportDocumentSetAdaptor(QObject *parent = 0);
virtual ~UBExportDocumentSetAdaptor();
virtual QString exportName();
virtual QString exportExtention();
virtual void persist(UBDocumentProxy* pDocument);
bool persistData(const QModelIndex &pRootIndex, QString filename);
bool addDocumentToZip(const QModelIndex &pIndex, UBDocumentTreeModel *model, QuaZip &zip);
virtual bool associatedActionactionAvailableFor(const QModelIndex &selectedIndex);
};
#endif // UBEXPORTDOCUMENTSETADAPTOR_H

@ -43,6 +43,7 @@
#include "domain/UBGraphicsPDFItem.h"
#include "document/UBDocumentProxy.h"
#include "document/UBDocumentController.h"
#include "pdf/GraphicsPDFItem.h"
@ -265,6 +266,16 @@ bool UBExportFullPDF::persistsDocument(UBDocumentProxy* pDocumentProxy, const QS
return true;
}
bool UBExportFullPDF::associatedActionactionAvailableFor(const QModelIndex &selectedIndex)
{
const UBDocumentTreeModel *docModel = qobject_cast<const UBDocumentTreeModel*>(selectedIndex.model());
if (!selectedIndex.isValid() || docModel->isCatalog(selectedIndex)) {
return false;
}
return true;
}
QString UBExportFullPDF::exportExtention()
{

@ -47,6 +47,7 @@ class UBExportFullPDF : public UBExportAdaptor
virtual QString exportName();
virtual QString exportExtention();
virtual void persist(UBDocumentProxy* pDocument);
virtual bool associatedActionactionAvailableFor(const QModelIndex &selectedIndex);
virtual bool persistsDocument(UBDocumentProxy* pDocument, const QString& filename);

@ -44,6 +44,7 @@
#include "domain/UBGraphicsPDFItem.h"
#include "document/UBDocumentProxy.h"
#include "document/UBDocumentController.h"
#include "pdf/GraphicsPDFItem.h"
@ -65,6 +66,16 @@ void UBExportPDF::persist(UBDocumentProxy* pDocumentProxy)
persistLocally(pDocumentProxy, tr("Export as PDF File"));
}
bool UBExportPDF::associatedActionactionAvailableFor(const QModelIndex &selectedIndex)
{
const UBDocumentTreeModel *docModel = qobject_cast<const UBDocumentTreeModel*>(selectedIndex.model());
if (!selectedIndex.isValid() || docModel->isCatalog(selectedIndex)) {
return false;
}
return true;
}
bool UBExportPDF::persistsDocument(UBDocumentProxy* pDocumentProxy, const QString& filename)
{

@ -46,6 +46,7 @@ class UBExportPDF : public UBExportAdaptor
virtual QString exportName();
virtual QString exportExtention();
virtual void persist(UBDocumentProxy* pDocument);
virtual bool associatedActionactionAvailableFor(const QModelIndex &selectedIndex);
virtual bool persistsDocument(UBDocumentProxy* pDocument, const QString& filename);
};

@ -0,0 +1,294 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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()
,""
,""
,false
,false
,true);
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;
}
}

@ -0,0 +1,50 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. 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

@ -0,0 +1,205 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBImportDocumentSetAdaptor.h"
#include "document/UBDocumentProxy.h"
#include "frameworks/UBFileSystemUtils.h"
#include "core/UBApplication.h"
#include "core/UBSettings.h"
#include "core/UBPersistenceManager.h"
#include "globals/UBGlobals.h"
THIRD_PARTY_WARNINGS_DISABLE
#include "quazip.h"
#include "quazipfile.h"
#include "quazipfileinfo.h"
THIRD_PARTY_WARNINGS_ENABLE
#include "core/memcheck.h"
UBImportDocumentSetAdaptor::UBImportDocumentSetAdaptor(QObject *parent)
:UBImportAdaptor(parent)
{
// NOOP
}
UBImportDocumentSetAdaptor::~UBImportDocumentSetAdaptor()
{
// NOOP
}
QStringList UBImportDocumentSetAdaptor::supportedExtentions()
{
return QStringList("ubx");
}
QString UBImportDocumentSetAdaptor::importFileFilter()
{
return tr("Open-Sankore (set of documents) (*.ubx)");
}
QFileInfoList UBImportDocumentSetAdaptor::importData(const QString &zipFile, const QString &destination)
{
//Create tmp directory to extract data, will be deleted after
QString tmpDir;
int i = 0;
QFileInfoList result;
do {
tmpDir = QDir::tempPath() + "/Sankore_tmpImportUBX_" + QString::number(i++);
} while (QFileInfo(tmpDir).exists());
QDir(QDir::tempPath()).mkdir(tmpDir);
QFile fZipFile(zipFile);
if (!extractFileToDir(fZipFile, tmpDir)) {
UBFileSystemUtils::deleteDir(tmpDir);
return QFileInfoList();
}
QDir tDir(tmpDir);
foreach(QFileInfo readDir, tDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden , QDir::Name)) {
QString newFileName = readDir.fileName();
if (QFileInfo(destination + "/" + readDir.fileName()).exists()) {
newFileName = QFileInfo(UBPersistenceManager::persistenceManager()->generateUniqueDocumentPath(tmpDir)).fileName();
}
QString newFilePath = destination + "/" + newFileName;
if (UBFileSystemUtils::copy(readDir.absoluteFilePath(), newFilePath)) {
result.append(newFilePath);
}
}
UBFileSystemUtils::deleteDir(tmpDir);
return result;
}
bool UBImportDocumentSetAdaptor::extractFileToDir(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 false;
}
zip.setFileNameCodec("UTF-8");
QuaZipFileInfo info;
QuaZipFile file(&zip);
QFile out;
char c;
QString documentRoot = QFileInfo(pDir).absoluteFilePath();
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 false;
}
if(!file.open(QIODevice::ReadOnly))
{
qWarning() << "Import failed. Cause: file.open(): " << zip.getZipError();
return false;
}
if(file.getZipError()!= UNZ_OK)
{
qWarning() << "Import failed. Cause: file.getFileName(): " << zip.getZipError();
return false;
}
QString actFileName = file.getActualFileName();
// int ind = actFileName.indexOf("/");
// if ( ind!= -1) {
// actFileName.remove(0, ind + 1);
// }
QString newFileName = documentRoot + "/" + actFileName;
QFileInfo newFileInfo(newFileName);
if (!rootDir.mkpath(newFileInfo.absolutePath()))
return false;
out.setFileName(newFileName);
if (!out.open(QIODevice::WriteOnly))
return false;
// 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 false;
}
while(file.getChar(&c))
out.putChar(c);
out.close();
if(file.getZipError()!=UNZ_OK)
{
qWarning() << "Import failed. Cause: " << zip.getZipError();
return false;
}
if(!file.atEnd())
{
qWarning() << "Import failed. Cause: read all but not EOF";
return false;
}
file.close();
if(file.getZipError()!=UNZ_OK)
{
qWarning() << "Import failed. Cause: file.close(): " << file.getZipError();
return false;
}
}
zip.close();
if(zip.getZipError()!=UNZ_OK)
{
qWarning() << "Import failed. Cause: zip.close(): " << zip.getZipError();
return false;
}
return true;
}

@ -0,0 +1,52 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBIMPORTDOCUMENTSETADAPTOR_H
#define UBIMPORTDOCUMENTSETADAPTOR_H
#include <QtGui>
#include "UBImportAdaptor.h"
class UBDocumentProxy;
class UBImportDocumentSetAdaptor : public UBImportAdaptor
{
Q_OBJECT
public:
UBImportDocumentSetAdaptor(QObject *parent = 0);
virtual ~UBImportDocumentSetAdaptor();
virtual QStringList supportedExtentions();
virtual QString importFileFilter();
QFileInfoList importData(const QString &zipFile, const QString &destination);
// virtual UBDocumentProxy* importFile(const QFile& pFile, const QString& pGroup);
// virtual bool addFileToDocument(UBDocumentProxy* pDocument, const QFile& pFile);
private:
bool extractFileToDir(const QFile& pZipFile, const QString& pDir);
};
#endif // UBIMPORTDOCUMENTSETADAPTOR_H

@ -0,0 +1,76 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBWebPublisher.h"
#include "document/UBDocumentProxy.h"
#include "document/UBDocumentController.h"
#include "adaptors/publishing/UBDocumentPublisher.h"
#include "core/memcheck.h"
UBWebPublisher::UBWebPublisher(QObject *parent)
: UBExportAdaptor(parent)
{
// NOOP
}
UBWebPublisher::~UBWebPublisher()
{
// NOOP
}
QString UBWebPublisher::exportName()
{
return tr("Publish Document on Sankore Web");
}
void UBWebPublisher::persist(UBDocumentProxy* pDocumentProxy)
{
if (!pDocumentProxy)
return;
//UniboardSankoreTransition document;
QString documentPath(pDocumentProxy->persistencePath());
//document.checkDocumentDirectory(documentPath);
UBDocumentPublisher* publisher = new UBDocumentPublisher(pDocumentProxy, this); // the publisher will self delete when publication finishes
publisher->publish();
}
bool UBWebPublisher::associatedActionactionAvailableFor(const QModelIndex &selectedIndex)
{
const UBDocumentTreeModel *docModel = qobject_cast<const UBDocumentTreeModel*>(selectedIndex.model());
if (!selectedIndex.isValid() || docModel->isCatalog(selectedIndex)) {
return false;
}
return true;
}

@ -0,0 +1,53 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBWEBPUBLISHER_H_
#define UBWEBPUBLISHER_H_
#include <QtGui>
#include "UBExportAdaptor.h"
#include "frameworks/UBFileSystemUtils.h"
#include "ui_webPublishing.h"
class UBDocumentProxy;
class UBServerXMLHttpRequest;
class UBWebPublisher : public UBExportAdaptor
{
Q_OBJECT
public:
UBWebPublisher(QObject *parent = 0);
virtual ~UBWebPublisher();
virtual QString exportName();
virtual void persist(UBDocumentProxy* pDocument);
virtual bool associatedActionactionAvailableFor(const QModelIndex &selectedIndex);
};
#endif /* UBWEBPUBLISHER_H_ */

@ -12,7 +12,13 @@ HEADERS += src/adaptors/UBExportAdaptor.h\
src/adaptors/UBImportImage.h \
src/adaptors/UBExportWeb.h \
src/adaptors/publishing/UBDocumentPublisher.h \
src/adaptors/publishing/UBSvgSubsetRasterizer.h
src/adaptors/publishing/UBSvgSubsetRasterizer.h \
$$PWD/UBExportDocumentSetAdaptor.h \
$$PWD/UBImportDocumentSetAdaptor.h \
$$PWD/UBExportCFF.h \
$$PWD/UBImportCFF.h \
$$PWD/UBWebPublisher.h \
$$PWD/UBCFFSubsetAdaptor.h
SOURCES += src/adaptors/UBExportAdaptor.cpp\
@ -28,4 +34,10 @@ SOURCES += src/adaptors/UBExportAdaptor.cpp\
src/adaptors/UBImportImage.cpp \
src/adaptors/UBExportWeb.cpp \
src/adaptors/publishing/UBDocumentPublisher.cpp\
src/adaptors/publishing/UBSvgSubsetRasterizer.cpp
src/adaptors/publishing/UBSvgSubsetRasterizer.cpp \
$$PWD/UBExportDocumentSetAdaptor.cpp \
$$PWD/UBImportDocumentSetAdaptor.cpp \
$$PWD/UBExportCFF.cpp \
$$PWD/UBImportCFF.cpp \
$$PWD/UBWebPublisher.cpp \
$$PWD/UBCFFSubsetAdaptor.cpp

@ -1,35 +1,669 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QFileInfo>
#include <QPushButton>
#include "UBDocumentPublisher.h"
#include "frameworks/UBPlatformUtils.h"
#include "frameworks/UBFileSystemUtils.h"
#include "frameworks/UBStringUtils.h"
#include "network/UBNetworkAccessManager.h"
#include "network/UBServerXMLHttpRequest.h"
#include "core/UBDocumentManager.h"
#include "core/UBApplication.h"
#include "core/UBPersistenceManager.h"
#include "core/UBApplicationController.h"
#include "board/UBBoardController.h"
#include "gui/UBMainWindow.h"
#include "document/UBDocumentProxy.h"
#include "document/UBDocumentContainer.h"
#include "domain/UBGraphicsWidgetItem.h"
#include "globals/UBGlobals.h"
THIRD_PARTY_WARNINGS_DISABLE
#include "quazip.h"
#include "quazipfile.h"
THIRD_PARTY_WARNINGS_ENABLE
#include "adaptors/UBExportFullPDF.h"
#include "adaptors/UBExportDocument.h"
#include "adaptors/UBSvgSubsetAdaptor.h"
#include "UBSvgSubsetRasterizer.h"
#include "../../core/UBApplication.h"
#include "core/memcheck.h"
UBDocumentPublisher::UBDocumentPublisher(UBDocumentProxy* pDocument, QObject *parent)
: QObject(parent)
, mSourceDocument(pDocument)
, mUsername("")
, mPassword("")
, bLoginCookieSet(false)
{
init();
}
UBDocumentPublisher::~UBDocumentPublisher()
{
}
void UBDocumentPublisher::publish()
{
//check that the username and password are stored on preferences
UBSettings* settings = UBSettings::settings();
if(settings->communityUsername().isEmpty() || settings->communityPassword().isEmpty()){
UBApplication::showMessage(tr("Credentials has to not been filled out yet."));
qDebug() << "trying to connect to community without the required credentials";
return;
}
mUsername = settings->communityUsername();
mPassword = settings->communityPassword();
UBPublicationDlg dlg;
if(QDialog::Accepted == dlg.exec())
{
mDocInfos.title = dlg.title();
mDocInfos.description = dlg.description();
buildUbwFile();
UBApplication::showMessage(tr("Uploading Sankore File on Web."));
sendUbw(mUsername, mPassword);
}
}
void UBDocumentPublisher::buildUbwFile()
{
QDir d;
d.mkpath(UBFileSystemUtils::defaultTempDirPath());
QString tmpDir = UBFileSystemUtils::createTempDir();
if (UBFileSystemUtils::copyDir(mSourceDocument->persistencePath(), tmpDir))
{
QString documentName = mSourceDocument->name();
//remove all the directory separators from the document name.
//we do not want to interperete them as directory separator
documentName = documentName.replace("/",".").replace("\\",".");
documentName = documentName.replace(":","-");
mPublishingPath = tmpDir;
mPublishingSize = mSourceDocument->pageCount();
rasterizeScenes();
upgradeDocumentForPublishing();
UBExportFullPDF pdfExporter;
pdfExporter.setVerbose(false);
pdfExporter.persistsDocument(mSourceDocument, mPublishingPath + "/" + documentName + ".pdf");
UBExportDocument ubzExporter;
ubzExporter.setVerbose(false);
ubzExporter.persistsDocument(mSourceDocument, mPublishingPath + "/" + documentName + ".ubz");
// remove all useless files
for (int pageIndex = 0; pageIndex < mPublishingSize; pageIndex++) {
QString filename = mPublishingPath + UBFileSystemUtils::digitFileFormat("/page%1.svg",pageIndex);
QFile::remove(filename);
}
UBFileSystemUtils::deleteDir(mPublishingPath + "/" + UBPersistenceManager::imageDirectory);
UBFileSystemUtils::deleteDir(mPublishingPath + "/" + UBPersistenceManager::objectDirectory);
UBFileSystemUtils::deleteDir(mPublishingPath + "/" + UBPersistenceManager::videoDirectory);
UBFileSystemUtils::deleteDir(mPublishingPath + "/" + UBPersistenceManager::audioDirectory);
mTmpZipFile = UBFileSystemUtils::defaultTempDirPath() + "/" + UBStringUtils::toCanonicalUuid(QUuid::createUuid()) + ".ubw";
QuaZip zip(mTmpZipFile);
zip.setFileNameCodec("UTF-8");
if (!zip.open(QuaZip::mdCreate))
{
qWarning() << "Export failed. Cause: zip.open(): " << zip.getZipError() << "," << mTmpZipFile;
QApplication::restoreOverrideCursor();
return;
}
QuaZipFile outFile(&zip);
if (!UBFileSystemUtils::compressDirInZip(mPublishingPath, "", &outFile, true))
{
qWarning("Export failed. compressDirInZip failed ...");
zip.close();
UBApplication::showMessage(tr("Export failed."));
QApplication::restoreOverrideCursor();
return;
}
if (zip.getZipError() != 0)
{
qWarning("Export failed. Cause: zip.close(): %d", zip.getZipError());
zip.close();
UBApplication::showMessage(tr("Export failed."));
QApplication::restoreOverrideCursor();
return;
}
zip.close();
}
else
{
UBApplication::showMessage(tr("Export canceled ..."));
QApplication::restoreOverrideCursor();
}
}
void UBDocumentPublisher::rasterizeScenes()
{
for (int pageIndex = 0; pageIndex < mPublishingSize; pageIndex++)
{
UBApplication::showMessage(tr("Converting page %1/%2 ...").arg(UBDocumentContainer::pageFromSceneIndex(pageIndex)).arg(mPublishingSize), true);
UBDocumentProxy publishingDocument(mPublishingPath);
UBSvgSubsetRasterizer rasterizer(&publishingDocument, pageIndex);
QString filename = mPublishingPath + UBFileSystemUtils::digitFileFormat("/page%1.jpg",pageIndex);
rasterizer.rasterizeToFile(filename);
}
}
void UBDocumentPublisher::updateGoogleMapApiKey()
{
/*
QDir widgestDir(mPublishingPath + "/" + UBPersistenceManager::widgetDirectory);
QString uniboardWebGoogleMapApiKey = UBSettings::settings()->uniboardWebGoogleMapApiKey->get().toString();
foreach(QFileInfo dirInfo, widgestDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot))
{
QString config = UBFileSystemUtils::readTextFile(dirInfo.absoluteFilePath() + "/config.xml").toLower();
if (config.contains("google") && config.contains("map"))
{
QDir widgetDir(dirInfo.absoluteFilePath());
foreach(QFileInfo fileInfo, widgetDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot))
{
QFile file(fileInfo.absoluteFilePath());
if (file.open(QIODevice::ReadWrite))
{
QTextStream stream(&file);
QString content = stream.readAll();
if (content.contains("ABQIAAAA6vtVqAUu8kZ_eTz7c8kwSBT9UCAhw_xm0LNFHsWmQxTJAdp5lxSY_5r-lZriY_7sACaMnl80JcX6Og"))
{
content.replace("ABQIAAAA6vtVqAUu8kZ_eTz7c8kwSBT9UCAhw_xm0LNFHsWmQxTJAdp5lxSY_5r-lZriY_7sACaMnl80JcX6Og",
uniboardWebGoogleMapApiKey);
file.resize(0);
file.write(content.toUtf8());
}
file.close();
}
}
}
}
*/
}
void UBDocumentPublisher::upgradeDocumentForPublishing()
{
for (int pageIndex = 0; pageIndex < mPublishingSize; pageIndex++)
{
UBDocumentProxy publishingDocument(mPublishingPath);
UBGraphicsScene *scene = UBSvgSubsetAdaptor::loadScene(&publishingDocument, pageIndex);
QList<UBGraphicsW3CWidgetItem*> widgets;
foreach(QGraphicsItem* item, scene->items()){
UBGraphicsW3CWidgetItem *widgetItem = dynamic_cast<UBGraphicsW3CWidgetItem*>(item);
if(widgetItem){
generateWidgetPropertyScript(widgetItem, UBDocumentContainer::pageFromSceneIndex(pageIndex));
widgets << widgetItem;
}
}
QString filename = mPublishingPath + UBFileSystemUtils::digitFileFormat("/page%1.json",pageIndex);
QFile jsonFile(filename);
if (jsonFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
jsonFile.write("{\n");
jsonFile.write(QString(" \"scene\": {\n").toUtf8());
jsonFile.write(QString(" \"x\": %1,\n").arg(scene->normalizedSceneRect().x()).toUtf8());
jsonFile.write(QString(" \"y\": %1,\n").arg(scene->normalizedSceneRect().y()).toUtf8());
jsonFile.write(QString(" \"width\": %1,\n").arg(scene->normalizedSceneRect().width()).toUtf8());
jsonFile.write(QString(" \"height\": %1\n").arg(scene->normalizedSceneRect().height()).toUtf8());
jsonFile.write(QString(" },\n").toUtf8());
jsonFile.write(QString(" \"widgets\": [\n").toUtf8());
bool first = true;
foreach(UBGraphicsW3CWidgetItem* widget, widgets)
{
if (!first)
jsonFile.write(QString(" ,\n").toUtf8());
jsonFile.write(QString(" {\n").toUtf8());
jsonFile.write(QString(" \"uuid\": \"%1\",\n").arg(UBStringUtils::toCanonicalUuid(widget->uuid())).toUtf8());
jsonFile.write(QString(" \"id\": \"%1\",\n").arg(widget->metadatas().id).toUtf8());
jsonFile.write(QString(" \"name\": \"%1\",\n").arg(widget->metadatas().name).toUtf8());
jsonFile.write(QString(" \"description\": \"%1\",\n").arg(widget->metadatas().description).toUtf8());
jsonFile.write(QString(" \"author\": \"%1\",\n").arg(widget->metadatas().author).toUtf8());
jsonFile.write(QString(" \"authorEmail\": \"%1\",\n").arg(widget->metadatas().authorEmail).toUtf8());
jsonFile.write(QString(" \"authorHref\": \"%1\",\n").arg(widget->metadatas().authorHref).toUtf8());
jsonFile.write(QString(" \"version\": \"%1\",\n").arg(widget->metadatas().authorHref).toUtf8());
jsonFile.write(QString(" \"x\": %1,\n").arg(widget->sceneBoundingRect().x()).toUtf8());
jsonFile.write(QString(" \"y\": %1,\n").arg(widget->sceneBoundingRect().y()).toUtf8());
jsonFile.write(QString(" \"width\": %1,\n").arg(widget->sceneBoundingRect().width()).toUtf8());
jsonFile.write(QString(" \"height\": %1,\n").arg(widget->sceneBoundingRect().height()).toUtf8());
jsonFile.write(QString(" \"nominalWidth\": %1,\n").arg(widget->boundingRect().width()).toUtf8());
jsonFile.write(QString(" \"nominalHeight\": %1,\n").arg(widget->boundingRect().height()).toUtf8());
QString url = UBPersistenceManager::widgetDirectory + "/" + widget->uuid().toString() + ".wgt";
jsonFile.write(QString(" \"src\": \"%1\",\n").arg(url).toUtf8());
QString startFile = widget->mainHtmlFileName();
jsonFile.write(QString(" \"startFile\": \"%1\",\n").arg(startFile).toUtf8());
QMap<QString, QString> preferences = widget->UBGraphicsWidgetItem::preferences();
jsonFile.write(QString(" \"preferences\": {\n").toUtf8());
foreach(QString key, preferences.keys())
{
QString sep = ",";
if (key == preferences.keys().last())
sep = "";
jsonFile.write(QString(" \"%1\": \"%2\"%3\n")
.arg(key)
.arg(preferences.value(key))
.arg(sep)
.toUtf8());
}
jsonFile.write(QString(" },\n").toUtf8());
jsonFile.write(QString(" \"datastore\": {\n").toUtf8());
QMap<QString, QString> datastoreEntries = widget->datastoreEntries();
foreach(QString entry, datastoreEntries.keys())
{
QString sep = ",";
if (entry == datastoreEntries.keys().last())
sep = "";
jsonFile.write(QString(" \"%1\": \"%2\"%3\n")
.arg(entry)
.arg(datastoreEntries.value(entry))
.arg(sep)
.toUtf8());
}
jsonFile.write(QString(" }\n").toUtf8());
jsonFile.write(QString(" }\n").toUtf8());
first = false;
}
jsonFile.write(" ]\n");
jsonFile.write("}\n");
}
else
{
qWarning() << "Cannot open file" << filename << "for saving page state";
}
delete scene;
}
updateGoogleMapApiKey();
}
void UBDocumentPublisher::generateWidgetPropertyScript(UBGraphicsW3CWidgetItem *widgetItem, int pageNumber)
{
QMap<QString, QString> preferences = widgetItem->UBGraphicsWidgetItem::preferences();
QMap<QString, QString> datastoreEntries = widgetItem->datastoreEntries();
QString startFileName = widgetItem->mainHtmlFileName();
if (!startFileName.startsWith("http://"))
{
QString startFilePath = mPublishingPath + "/" + UBPersistenceManager::widgetDirectory + "/" + widgetItem->uuid().toString() + ".wgt/" + startFileName;
QFile startFile(startFilePath);
if (startFile.exists())
{
if (startFile.open(QIODevice::ReadWrite))
{
QTextStream stream(&startFile);
QStringList lines;
bool addedJs = false;
QString line;
do
{
line = stream.readLine();
if (!line.isNull())
{
lines << line;
if (!addedJs && line.contains("<head") && line.contains(">") ) // TODO UB 4.6, this is naive ... the HEAD tag may be on several lines
{
lines << "";
lines << " <script type=\"text/javascript\">";
lines << " var widget = {};";
lines << " widget.id = '" + widgetItem->metadatas().id + "';";
lines << " widget.name = '" + widgetItem->metadatas().name + "';";
lines << " widget.description = '" + widgetItem->metadatas().description + "';";
lines << " widget.author = '" + widgetItem->metadatas().author + "';";
lines << " widget.authorEmail = '" + widgetItem->metadatas().authorEmail + "';";
lines << " widget.authorHref = '" + widgetItem->metadatas().authorHref + "';";
lines << " widget.version = '" + widgetItem->metadatas().version + "';";
lines << " widget.uuid = '" + UBStringUtils::toCanonicalUuid(widgetItem->uuid()) + "';";
lines << " widget.width = " + QString("%1").arg(widgetItem->nominalSize().width()) + ";";
lines << " widget.height = " + QString("%1").arg(widgetItem->nominalSize().height()) + ";";
lines << " widget.openUrl = function(url) { window.open(url); }";
lines << " widget.preferences = new Array()";
foreach(QString pref, preferences.keys())
{
lines << " widget.preferences['" + pref + "'] = '" + preferences.value(pref) + "';";
}
lines << " widget.preferences.key = function(index) {";
lines << " var currentIndex = 0;";
lines << " for(key in widget.preferences){";
lines << " if (currentIndex == index){ return key;}";
lines << " currentIndex++;";
lines << " }";
lines << " return '';";
lines << " }";
lines << " widget.preferences.getItem = function(key) {";
lines << " return widget.preferences[key];";
lines << " }";
lines << " widget.preferences.setItem = function(key, value) {}";
lines << " widget.preferences.removeItem = function(key) {}";
lines << " widget.preferences.clear = function() {}";
lines << " var uniboard = {};";
lines << " uniboard.pageCount = " + QString("%1").arg(mPublishingSize) + ";";
lines << " uniboard.currentPageNumber = " + QString("%1").arg(pageNumber) + ";";
lines << " uniboard.uuid = '" + UBStringUtils::toCanonicalUuid(widgetItem->uuid()) + "'";
lines << " uniboard.lang = navigator.language;";
lines << " uniboard.locale = function() {return navigator.language}";
lines << " uniboard.messages = {}";
lines << " uniboard.messages.subscribeToTopic = function(topicName){}";
lines << " uniboard.messages.unsubscribeFromTopic = function(topicName){}";
lines << " uniboard.messages.sendMessage = function(topicName, message){}";
lines << " uniboard.datastore = {};";
lines << " uniboard.datastore.document = new Array();";
foreach(QString entry, datastoreEntries.keys())
{
lines << " uniboard.datastore.document['" + entry + "'] = '" + datastoreEntries.value(entry) + "';";
}
lines << " uniboard.datastore.document.key = function(index) {";
lines << " var currentIndex = 0;";
lines << " for(key in uniboard.datastore.document){";
lines << " if (currentIndex == index){ return key;}";
lines << " currentIndex++;";
lines << " }";
lines << " return '';";
lines << " }";
lines << " uniboard.datastore.document.getItem = function(key) {";
lines << " return uniboard.datastore.document[key];";
lines << " }";
lines << " uniboard.datastore.document.setItem = function(key, value) {}";
lines << " uniboard.datastore.document.removeItem = function(key) {}";
lines << " uniboard.datastore.document.clear = function() {}";
lines << " uniboard.setTool = function(tool){}";
lines << " uniboard.setPenColor = function(color){}";
lines << " uniboard.setMarkerColor = function(color){}";
lines << " uniboard.pageThumbnail = function(pageNumber){";
lines << " var nb;";
lines << " if (pageNumber < 10) return 'page00' + pageNumber + '.thumbnail.jpg';";
lines << " if (pageNumber < 100) return 'page0' + pageNumber + '.thumbnail.jpg';";
lines << " return 'page' + pageNumber + '.thumbnail.jpg;'";
lines << " }";
lines << " uniboard.zoom = function(factor, x, y){}";
lines << " uniboard.move = function(x, y){}";
lines << " uniboard.move = function(x, y){}";
lines << " uniboard.moveTo = function(x, y){}";
lines << " uniboard.drawLineTo = function(x, y, width){}";
lines << " uniboard.eraseLineTo = function(x, y, width){}";
lines << " uniboard.clear = function(){}";
lines << " uniboard.setBackground = function(dark, crossed){}";
lines << " uniboard.addObject = function(url, width, height, x, y, background){}";
lines << " uniboard.resize = function(width, height){window.resizeTo(width, height);}";
lines << " uniboard.showMessage = function(message){alert(message);}";
lines << " uniboard.centerOn = function(x, y){}";
lines << " uniboard.addText = function(text, x, y){}";
lines << " uniboard.setPreference = function(key, value){}";
lines << " uniboard.preference = function(key, defValue){";
lines << " var pref = widget.preferences[key];";
lines << " if (pref == undefined) ";
lines << " return defValue;";
lines << " else ";
lines << " return pref;";
lines << " }";
lines << " uniboard.preferenceKeys = function(){";
lines << " var keys = new Array();";
lines << " for(key in widget.preferences){";
lines << " keys.push(key);";
lines << " }";
lines << " return keys;";
lines << " }";
lines << " uniboard.datastore.document.key = function(index) {";
lines << " var currentIndex = 0;";
lines << " for(key in uniboard.datastore.document){";
lines << " if (currentIndex == index){ return key;}";
lines << " currentIndex++;";
lines << " }";
lines << " return '';";
lines << " }";
lines << " uniboard.datastore.document.getItem = function(key) {";
lines << " return uniboard.datastore.document[key];";
lines << " }";
lines << " uniboard.datastore.document.setItem = function(key, value) {}";
lines << " uniboard.datastore.document.removeItem = function(key) {}";
lines << " uniboard.datastore.document.clear = function() {}";
lines << " </script>";
lines << "";
addedJs = true;
}
}
}
while (!line.isNull());
startFile.resize(0);
startFile.write(lines.join("\n").toUtf8()); // TODO UB 4.x detect real html encoding
startFile.close();
}
}
}
else{
qWarning() << "Remote Widget start file, cannot inject widget preferences and datastore entries";
}
}
void UBDocumentPublisher::init()
{
mCrlf=0x0d;
mCrlf+=0x0a;
mDocInfos.title = "";
mDocInfos.description = "";
mpCookieJar = new QNetworkCookieJar();
mpNetworkMgr = new QNetworkAccessManager(this);
connect(mpNetworkMgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
}
void UBDocumentPublisher::onFinished(QNetworkReply *reply)
{
QVariant cookieHeader = reply->rawHeader("Set-Cookie");
// First we concatenate all the Set-Cookie values (the packet can contains many of them)
QStringList qslCookie = cookieHeader.toString().split("\n");
QString qsCookieValue = qslCookie.at(0);
for (int i = 1; i < qslCookie.size(); i++) {
qsCookieValue += "; " +qslCookie.at(i);
}
// Now we isolate every cookie value
QStringList qslCookieVals = qsCookieValue.split("; ");
bool bTransferOk = false;
for(int j = 0; j < qslCookieVals.size(); j++)
{
qDebug() << j << qslCookieVals.at(j);
if(qslCookieVals.at(j).startsWith("assetStatus"))
{
QStringList qslAsset = qslCookieVals.at(j).split("=");
if(qslAsset.at(1) == "UPLOADED")
{
bTransferOk = true;
break;
}
}
}
if(bTransferOk)
{
UBApplication::showMessage(tr("Document uploaded correctly on the web."));
}
else
{
UBApplication::showMessage(tr("Failed to upload document on the web."));
}
reply->deleteLater();
}
void UBDocumentPublisher::sendUbw(QString username, QString password)
{
if (QFile::exists(mTmpZipFile))
{
QFile f(mTmpZipFile);
if (f.open(QIODevice::ReadOnly))
{
QFileInfo fi(f);
QByteArray ba = f.readAll();
QString boundary,data, multipartHeader;
QByteArray datatoSend;
boundary = "---WebKitFormBoundaryDKBTgA53MiyWrzLY";
multipartHeader = "multipart/form-data; boundary="+boundary;
data="--"+boundary+mCrlf;
data+="Content-Disposition: form-data; name=\"title\"" + mCrlf + mCrlf + mDocInfos.title + mCrlf;
data+="--"+boundary+mCrlf;
data+="Content-Disposition: form-data; name=\"description\"" + mCrlf + mCrlf + mDocInfos.description.remove("\n") + mCrlf;
data+="--"+boundary+mCrlf;
data+="Content-Disposition: form-data; name=\"file\"; filename=\""+ fi.fileName() +"\""+mCrlf;
data+="Content-Type: application/octet-stream"+mCrlf+mCrlf;
datatoSend=data.toLatin1(); // convert data string to byte array for request
datatoSend += ba;
datatoSend += mCrlf;
datatoSend += QString("--%0--%1").arg(boundary).arg(mCrlf);
QNetworkRequest request(QUrl(QString(DOCPUBLICATION_URL).toLatin1().constData()));
request.setHeader(QNetworkRequest::ContentTypeHeader, multipartHeader);
request.setHeader(QNetworkRequest::ContentLengthHeader,datatoSend.size());
QString b64Auth = getBase64Of(QString("%0:%1").arg(username).arg(password));
request.setRawHeader("Authorization", QString("Basic %0").arg(b64Auth).toLatin1().constData());
request.setRawHeader("Host", "planete.sankore.org");
request.setRawHeader("Accept", "*/*");
request.setRawHeader("Accept-Language", "en-US,*");
mpCookieJar->setCookiesFromUrl(mCookies, QUrl(DOCPUBLICATION_URL));
mpNetworkMgr->setCookieJar(mpCookieJar);
// Send the file
mpNetworkMgr->post(request,datatoSend);
}
}
}
QString UBDocumentPublisher::getBase64Of(QString stringToEncode)
{
return stringToEncode.toLatin1().toBase64();
}
// ---------------------------------------------------------
UBProxyLoginDlg::UBProxyLoginDlg(QWidget *parent, const char *name):QDialog(parent)
, mpLayout(NULL)
, mpUserLayout(NULL)

@ -1,44 +1,34 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBDOCUMENTPUBLISHER_H
#define UBDOCUMENTPUBLISHER_H
#include <QtGui>
#include <QtNetwork>
#include <QDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include "ui_webPublishing.h"
#define DOCPUBLICATION_URL "http://planete.sankore.org/xwiki/bin/view/CreateResources/UniboardUpload?xpage=plain&outputSyntax=plain"
typedef struct
{
@ -94,4 +84,58 @@ private:
QTextEdit* mpDescription;
QDialogButtonBox* mpButtons;
};
class UBDocumentPublisher : public QObject
{
Q_OBJECT;
public:
explicit UBDocumentPublisher(UBDocumentProxy* sourceDocument, QObject *parent = 0);
virtual ~UBDocumentPublisher();
void publish();
signals:
void loginDone();
protected:
virtual void updateGoogleMapApiKey();
virtual void rasterizeScenes();
virtual void upgradeDocumentForPublishing();
virtual void generateWidgetPropertyScript(UBGraphicsW3CWidgetItem *widgetItem, int pageNumber);
private slots:
void onFinished(QNetworkReply* reply);
private:
UBDocumentProxy *mSourceDocument;
//UBDocumentProxy *mPublishingDocument;
QString mPublishingPath;
int mPublishingSize;
void init();
void sendUbw(QString username, QString password);
QString getBase64Of(QString stringToEncode);
QHBoxLayout* mpLayout;
QNetworkAccessManager* mpNetworkMgr;
QNetworkCookieJar* mpCookieJar;
QString mUsername;
QString mPassword;
QString mCrlf;
bool bLoginCookieSet;
void buildUbwFile();
QString mTmpZipFile;
QList<QNetworkCookie> mCookies;
sDocumentInfos mDocInfos;
};
#endif // UBDOCUMENTPUBLISHER_H

@ -1,32 +1,26 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBSvgSubsetRasterizer.h"
#include "domain/UBGraphicsScene.h"

@ -1,32 +1,26 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBSVGSUBSETRASTERIZER_H_
#define UBSVGSUBSETRASTERIZER_H_

@ -854,7 +854,6 @@ void UBBoardController::blackout()
UBApplication::applicationController->blackout();
}
void UBBoardController::showKeyboard(bool show)
{
if(show)
@ -1993,7 +1992,7 @@ void UBBoardController::persistCurrentScene(bool isAnAutomaticBackup, bool force
&& (mActiveSceneIndex >= 0) && mActiveSceneIndex != mMovingSceneIndex
&& (mActiveScene->isModified()))
{
UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex, isAnAutomaticBackup,forceImmediateSave);
UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex);
updatePage(mActiveSceneIndex);
}
}

@ -253,6 +253,8 @@ class UBBoardController : public UBDocumentContainer
void saveData(SaveFlags fls = sf_none);
//void regenerateThumbnails();
signals:
void newPageAdded();
void activeSceneChanged();

@ -635,6 +635,7 @@ void UBApplicationController::mirroringEnabled(bool enabled)
}
void UBApplicationController::closing()
{
if (mMirror)
@ -642,12 +643,18 @@ void UBApplicationController::closing()
if (mUninoteController)
{
mUninoteController->hideWindow();
mUninoteController->close();
}
/*
if (UBApplication::documentController)
UBApplication::documentController->closing();
*/
UBPersistenceManager::persistenceManager()->closing(); // ALTI/AOU - 20140616 : to update the file "documents/folders.xml"
}

@ -1,32 +1,26 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBDocumentManager.h"
#include "frameworks/UBStringUtils.h"
@ -34,9 +28,14 @@
#include "adaptors/UBExportFullPDF.h"
#include "adaptors/UBExportDocument.h"
#include "adaptors/UBExportWeb.h"
#include "adaptors/UBExportCFF.h"
#include "adaptors/UBExportDocumentSetAdaptor.h"
#include "adaptors/UBWebPublisher.h"
#include "adaptors/UBImportDocument.h"
#include "adaptors/UBImportPDF.h"
#include "adaptors/UBImportImage.h"
#include "adaptors/UBImportCFF.h"
#include "adaptors/UBImportDocumentSetAdaptor.h"
#include "domain/UBGraphicsScene.h"
#include "domain/UBGraphicsSvgItem.h"
@ -50,6 +49,8 @@
#include "UBSettings.h"
#include "UBPersistenceManager.h"
#include "../adaptors/UBExportWeb.h"
#include "core/memcheck.h"
UBDocumentManager* UBDocumentManager::sDocumentManager = 0;
@ -73,17 +74,30 @@ UBDocumentManager::UBDocumentManager(QObject *parent)
QString dummyObjects = tr("objects");
QString dummyWidgets = tr("widgets");
UBExportCFF* cffExporter = new UBExportCFF(this);
UBExportFullPDF* exportFullPdf = new UBExportFullPDF(this);
UBExportDocument* exportDocument = new UBExportDocument(this);
UBWebPublisher* webPublished = new UBWebPublisher(this);
UBExportDocumentSetAdaptor *exportDocumentSet = new UBExportDocumentSetAdaptor(this);
mExportAdaptors.append(exportDocument);
mExportAdaptors.append(exportDocumentSet);
mExportAdaptors.append(webPublished);
mExportAdaptors.append(exportFullPdf);
mExportAdaptors.append(cffExporter);
// UBExportWeb* exportWeb = new UBExportWeb(this);
// mExportAdaptors.append(exportWeb);
UBImportDocument* documentImport = new UBImportDocument(this);
mImportAdaptors.append(documentImport);
UBImportDocumentSetAdaptor *documentSetImport = new UBImportDocumentSetAdaptor(this);
mImportAdaptors.append(documentSetImport);
UBImportPDF* pdfImport = new UBImportPDF(this);
mImportAdaptors.append(pdfImport);
UBImportImage* imageImport = new UBImportImage(this);
mImportAdaptors.append(imageImport);
UBImportCFF* cffImport = new UBImportCFF(this);
mImportAdaptors.append(cffImport);
}
@ -93,38 +107,60 @@ UBDocumentManager::~UBDocumentManager()
}
QStringList UBDocumentManager::importFileExtensions()
QStringList UBDocumentManager::importFileExtensions(bool notUbx)
{
QStringList result;
foreach (UBImportAdaptor *importAdaptor, mImportAdaptors)
{
result << importAdaptor->supportedExtentions();
//issue 1629 - NNE - 20131213 : add test to remove ubx extention if necessary
if(!(notUbx && importAdaptor->supportedExtentions().at(0) == "ubx")){
result << importAdaptor->supportedExtentions();
}
}
return result;
}
QString UBDocumentManager::importFileFilter()
QString UBDocumentManager::importFileFilter(bool notUbx)
{
QString result;
result += tr("All supported files (*.%1)").arg(importFileExtensions().join(" *."));
result += tr("All supported files (*.%1)").arg(importFileExtensions(notUbx).join(" *."));
foreach (UBImportAdaptor *importAdaptor, mImportAdaptors)
{
if (importAdaptor->importFileFilter().length() > 0)
{
if (result.length())
{
result += ";;";
//issue 1629 - NNE - 20131213 : Add a test on ubx before put in the list
if(!(notUbx && importAdaptor->supportedExtentions().at(0) == "ubx")){
if (result.length())
{
result += ";;";
}
result += importAdaptor->importFileFilter();
}
result += importAdaptor->importFileFilter();
}
}
qDebug() << "import file filter" << result;
return result;
}
QFileInfoList UBDocumentManager::importUbx(const QString &Incomingfile, const QString &destination)
{
UBImportDocumentSetAdaptor *docSetAdaptor;
foreach (UBImportAdaptor *curAdaptor, mImportAdaptors) {
docSetAdaptor = qobject_cast<UBImportDocumentSetAdaptor*>(curAdaptor);
if (docSetAdaptor) {
break;
}
}
if (!docSetAdaptor) {
return QFileInfoList();
}
return docSetAdaptor->importData(Incomingfile, destination);
}
UBDocumentProxy* UBDocumentManager::importFile(const QFile& pFile, const QString& pGroup)
{
@ -150,7 +186,12 @@ UBDocumentProxy* UBDocumentManager::importFile(const QFile& pFile, const QString
// Document import procedure.....
QString documentName = QFileInfo(pFile.fileName()).completeBaseName();
document = UBPersistenceManager::persistenceManager()->createDocument(pGroup, documentName,false);
document = UBPersistenceManager::persistenceManager()->createDocument(pGroup
,documentName
, false // Issue 1630 - CFA - 201410503 - suppression de la page vide ajoutee à l'import des pdfs
, QString()
, 0
, true);
QUuid uuid = QUuid::createUuid();
QString filepath = pFile.fileName();
@ -159,7 +200,6 @@ UBDocumentProxy* UBDocumentManager::importFile(const QFile& pFile, const QString
bool b = UBPersistenceManager::persistenceManager()->addFileToDocument(document, pFile.fileName(), importAdaptor->folderToCopy() , uuid, filepath);
if (!b)
{
UBPersistenceManager::persistenceManager()->deleteDocument(document);
UBApplication::setDisabled(false);
return NULL;
}
@ -169,8 +209,9 @@ UBDocumentProxy* UBDocumentManager::importFile(const QFile& pFile, const QString
int nPage = 0;
foreach(UBGraphicsItem* page, pages)
{
UBApplication::showMessage(tr("Inserting page %1 of %2").arg(++nPage).arg(pages.size()), true);
#ifdef Q_OS_OSX
#ifdef Q_WS_MACX
//Workaround for issue 912
QApplication::processEvents();
#endif
@ -211,9 +252,11 @@ int UBDocumentManager::addFilesToDocument(UBDocumentProxy* document, QStringList
if (adaptor->isDocumentBased())
{
UBDocumentBasedImportAdaptor* importAdaptor = (UBDocumentBasedImportAdaptor*)adaptor;
//issue 1629 - NNE - 20131212 : Resolve a segfault, but for .ubx, actually
//the file will be not imported...
UBDocumentBasedImportAdaptor* importAdaptor = dynamic_cast<UBDocumentBasedImportAdaptor*>(adaptor);
if (importAdaptor->addFileToDocument(document, file))
if (importAdaptor && importAdaptor->addFileToDocument(document, file))
nImportedDocuments++;
}
else
@ -240,7 +283,7 @@ int UBDocumentManager::addFilesToDocument(UBDocumentProxy* document, QStringList
UBGraphicsScene* scene = UBPersistenceManager::persistenceManager()->createDocumentSceneAt(document, pageIndex);
importAdaptor->placeImportedItemToScene(scene, page);
UBPersistenceManager::persistenceManager()->persistDocumentScene(document, scene, pageIndex);
UBApplication::boardController->addEmptyThumbPage();
UBApplication::boardController->insertThumbPage(pageIndex);
}
UBPersistenceManager::persistenceManager()->persistDocumentMetadata(document);

@ -45,9 +45,12 @@ class UBDocumentManager : public QObject
static UBDocumentManager* documentManager();
virtual ~UBDocumentManager();
QString importFileFilter();
QStringList importFileExtensions();
QString importFileFilter(bool notUbx = false);
QStringList importFileExtensions(bool notUbx = false);
QFileInfoList importUbx(const QString &Incomingfile, const QString &destination);
UBDocumentProxy* importFile(const QFile& pFile, const QString& pGroup);
int addFilesToDocument(UBDocumentProxy* pDocument, QStringList fileNames);

@ -0,0 +1,628 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBForeignObjectsHandler.h"
#include <QtGui>
#include <QtXml>
#include "UBSettings.h"
const QString tVideo = "video";
const QString tAudio = "audio";
const QString tImage = "image";
const QString tForeignObject = "foreignObject";
const QString tTeacherGuide = "teacherGuide";
const QString tMedia = "media";
const QString tGroups = "groups";
const QString aHref = "xlink:href";
const QString aType = "ub:type";
const QString aReqExt = "requiredExtensions";
const QString aSrc = "ub:src";
const QString aMediaType = "mediaType";
const QString aRelativePath = "relativePath";
const QString aActionMedia = "ub:actionFirstParameter";
const QString vText = "text";
const QString vReqExt = "http://ns.adobe.com/pdf/1.3/";
const QString wgtSuff = ".wgt";
const QString thumbSuff = ".png";
const QString scanDirs = "audios,images,videos,teacherGuideObjects,widgets";
const QStringList trashFilter = QStringList() << "*.swf";
static QString strIdFrom(const QString &filePath)
{
if ((filePath).isEmpty()) {
return QString();
}
QRegExp rx("\\{.(?!.*\\{).*\\}");
if (rx.indexIn(filePath) == -1) {
return QString();
}
return rx.cap();
}
static bool rm_r(const QString &rmPath)
{
QFileInfo fi(rmPath);
if (!fi.exists()) {
qDebug() << rmPath << "does not exist";
return false;
} else if (fi.isFile()) {
if (!QFile::remove(rmPath)) {
qDebug() << "can't remove file" << rmPath;
return false;
}
return true;
} else if (fi.isDir()) {
QFileInfoList fList = QDir(rmPath).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
foreach (QFileInfo sub, fList) {
rm_r(sub.absoluteFilePath());
}
if (!QDir().rmdir(rmPath)) {
qDebug() << "can't remove dir" << rmPath;
return false;
}
return true;
}
return false;
}
static bool cp_rf(const QString &what, const QString &where)
{
QFileInfo whatFi(what);
QFileInfo whereFi = QFileInfo(where);
if (!whatFi.exists()) {
qDebug() << what << "does not exist" << Q_FUNC_INFO;
return false;
} else if (whatFi.isFile()) {
QString whereDir = where.section("/", 0, -2, QString::SectionSkipEmpty | QString::SectionIncludeLeadingSep);
QString newFilePath = where;
if (!whereFi.exists()) {
QDir().mkpath(whereDir);
} else if (whereFi.isDir()) {
newFilePath = whereDir + "/" + whatFi.fileName();
}
if (QFile::exists(newFilePath)) {
QFile::remove(newFilePath);
}
if (!QFile::copy(what, newFilePath)) {
qDebug() << "can't copy" << what << "to" << where << Q_FUNC_INFO;
return false;
}
return true;
} else if (whatFi.isDir()) {
if (whereFi.isFile() && whereFi.fileName().toLower() == whatFi.fileName().toLower()) {
qDebug() << "can't copy dir" << what << "to file" << where << Q_FUNC_INFO;
return false;
} else if (whereFi.isDir()) {
rm_r(where);
}
QDir().mkpath(where);
QFileInfoList fList = QDir(what).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
foreach (QFileInfo sub, fList) {
if (!cp_rf(sub.absoluteFilePath(), where + "/" + sub.fileName()))
return false;
}
return true;
}
return true;
}
static QString thumbFileNameFrom(const QString &filePath)
{
if (filePath.isEmpty()) {
return QString();
}
QString thumbPath = filePath;
thumbPath.replace(QRegExp("[\\{\\}]"), "").replace(wgtSuff, thumbSuff);
return thumbPath;
}
QString svgPageName(int pageIndex)
{
return QString("page%1.svg").arg(pageIndex, 3, 10, QLatin1Char('0'));
}
static QDomDocument createDomFromSvg(const QString &svgUrl)
{
Q_ASSERT(QFile::exists(svgUrl));
QString mFoldersXmlStorageName = svgUrl;
if (QFileInfo(mFoldersXmlStorageName).exists()) {
QDomDocument xmlDom;
QFile inFile(mFoldersXmlStorageName);
if (inFile.open(QIODevice::ReadOnly)) {
QString domString(inFile.readAll());
int errorLine = 0; int errorColumn = 0;
QString errorStr;
if (xmlDom.setContent(domString, &errorStr, &errorLine, &errorColumn)) {
return xmlDom;
} else {
qDebug() << "Error reading content of " << mFoldersXmlStorageName << endl
<< "Error:" << inFile.errorString()
<< "Line:" << errorLine
<< "Column:" << errorColumn;
}
inFile.close();
} else {
qDebug() << "Error reading" << mFoldersXmlStorageName << endl
<< "Error:" << inFile.errorString();
}
}
return QDomDocument();
}
class Cleaner
{
public:
void cure(const QUrl &dir)
{
mCurrentDir = dir.toLocalFile();
cleanTrash();
// Gathering information from svg files
QFileInfoList svgInfos = QDir(mCurrentDir).entryInfoList(QStringList() << "*.svg", QDir::NoDotAndDotDot | QDir::Files);
foreach (QFileInfo svgInfo, svgInfos) {
cureIdsFromSvgDom(createDomFromSvg(svgInfo.absoluteFilePath()));
}
fitIdsFromFileSystem();
QVector<QString> deleteCandidates;
findRedundandElements(deleteCandidates);
foreach (QString key, deleteCandidates) {
QString delPath = mPresentIdsMap.value(key);
if (delPath.isNull()) {
continue;
} else if (delPath.endsWith(wgtSuff)) { //remove corresponding thumb
QString thumbPath = thumbFileNameFrom(delPath);
//N/C - NNE - 20140417
if (QFile::exists(thumbPath)) {
rm_r(thumbPath);
}
}
rm_r(delPath);
// Clear parent dir if empty
QDir dir(delPath);
dir.cdUp();
if (dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot).isEmpty()) {
dir.rmdir(dir.absolutePath());
}
}
qDebug() << "Ok on cure";
}
private:
void cleanTrash()
{
QFileInfoList ifs = QDir(mCurrentDir).entryInfoList(trashFilter, QDir::NoDotAndDotDot | QDir::Files);
foreach (QFileInfo ifo, ifs) {
rm_r(ifo.absoluteFilePath());
}
}
void cureIdsFromSvgDom(const QDomDocument &dom)
{
Q_ASSERT(!dom.isNull());
QDomElement nextElement = dom.documentElement().firstChildElement();
while (!nextElement.isNull()) {
QString nextTag = nextElement.tagName();
qDebug() << "Tag name of the next parsed element is" << nextTag;
if (nextTag == tGroups)
{
nextElement = nextElement.firstChildElement("group");
}
invokeFromText(nextTag, nextElement);
nextElement = nextElement.nextSiblingElement();
}
}
void fitIdsFromFileSystem()
{
QString absPrefix = mCurrentDir + "/";
QStringList dirsList = scanDirs.split(",", QString::SkipEmptyParts);
foreach (QString dirName, dirsList) {
QString absPath = absPrefix + dirName;
if (!QFile::exists(absPath)) {
continue;
}
fitIdsFromDir(absPath);
}
}
void fitIdsFromDir(const QString &scanDir)
{
QFileInfoList fileList = QDir(scanDir).entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
foreach (QFileInfo nInfo, fileList) {
QString uid = strIdFrom(nInfo.fileName());
if (uid.isNull()) {
continue;
}
mPresentIdsMap.insert(uid, nInfo.absoluteFilePath());
}
}
void findRedundandElements(QVector<QString> &v)
{
// Taking information from the physical file system
QStringList domIds = mDomIdsMap.keys();
QStringList presentIds = mPresentIdsMap.keys();
v.resize(qMax(domIds.count(), presentIds.count()));
QVector<QString>::iterator it_diff;
it_diff=std::set_symmetric_difference(domIds.begin(), domIds.end()
, presentIds.begin(), presentIds.end()
, v.begin());
v.resize(it_diff - v.begin());
}
void invokeFromText(const QString &what, const QDomElement &element)
{
if (what == tVideo
|| what == tAudio
|| what == tImage) {
mediaToContainer(element);
} else if (what == tForeignObject) {
foreingObjectToContainer(element);
//N/C - NNE - 20140317
cleanObjectFolder(element);
//N/C - NNE - 20140520
//foreign object may referer resource which are not present in the svg
addResourceIdToSvg(element);
} else if (what == tTeacherGuide) {
teacherGuideToContainer(element);
}
pullActionFromElement(element);
}
// N/C - NNE - 20140317 : When export, reduce the size of the ubz file
void cleanObjectFolder(const QDomElement &element)
{
//QDomElement preference = element.firstChildElement("ub:preference");
//N/C - NNE - 20141021
QDomNodeList childrenNode = element.elementsByTagName("ub:preference");
QVector<QString> objectsIdUsed;
for(int i = 0; i < childrenNode.size(); i++){
QDomElement preference = childrenNode.at(i).toElement();
if(!preference.isNull()){
QString value = preference.attribute("value");
int findPos = value.indexOf("objects/");
int endPos;
//find all objects used
while(findPos != -1){
endPos = value.indexOf("\"", findPos);
objectsIdUsed << value.mid(findPos, endPos - findPos);
findPos = value.indexOf("objects/", endPos);
}
}
}
//N/C - NNE - 20141021 : END
QString path = element.attribute(aSrc);
QString objectsFolderPath = mCurrentDir + "/" + path + "/objects/";
QDir dir(objectsFolderPath);
dir.setFilter(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
//then check all files in the objects directory
//delete the file not used (not in te objectIdUsed variable)
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); i++) {
QFileInfo fileInfo = list.at(i);
if(!objectsIdUsed.contains("objects/"+fileInfo.fileName())){
QFile(fileInfo.filePath()).remove();
}
}
}
// N/C - NNE - 20140317 : END
//N/C - NNE - 20140520
void addResourceIdToSvg(const QDomElement& element)
{
QDomElement textContent = element.firstChildElement("itemTextContent");
QString value = textContent.text();
int findPos = value.indexOf("images/");
int endPos;
//find all objects used
while(findPos != -1){
endPos = value.indexOf("\"", findPos);
QString path = value.mid(findPos, endPos - findPos);
QString uuid = path.split("/").at(1).split(".").at(0);
mDomIdsMap.insert(uuid, path);
findPos = value.indexOf("images/", endPos);
}
}
//N/C - NNE - 20140520 : END
void pullActionFromElement(const QDomElement &element)
{
if (!element.hasAttribute(aActionMedia)) {
return;
}
QString path = element.attribute(aActionMedia);
if (path.isNull()) {
return;
}
QString uid = strIdFrom(path);
if (uid.isNull()) {
return;
}
mDomIdsMap.insert(uid, path);
}
void teacherGuideToContainer(const QDomElement &element)
{
QDomElement nMediaElement = element.firstChildElement(tMedia);
while (!nMediaElement.isNull()) {
QString path = nMediaElement.attribute(aRelativePath);
if (path.isNull()) {
continue;
}
QString uid = strIdFrom(path);
if (uid.isNull()) {
return;
}
mDomIdsMap.insert(uid, path);
nMediaElement = nMediaElement.nextSiblingElement(tMedia);
}
}
void mediaToContainer(const QDomElement &element)
{
QString path = element.attribute(aHref);
if (path.isNull()) {
return;
}
QString uid = strIdFrom(path);
if (uid.isNull()) {
return;
}
mDomIdsMap.insert(uid, path);
}
void foreingObjectToContainer(const QDomElement &element)
{
QString type = element.attribute(aType);
if (type == vText) { // We don't have to care of the text object
return;
}
QString path = element.attribute(aSrc);
if (path.isNull()) {
return;
}
QString uid = strIdFrom(path);
if (uid.isNull()) {
return;
}
mDomIdsMap.insert(uid, path);
}
private:
QString mCurrentDir;
QDomDocument mSvgData;
QMap<QString, QString> mDomIdsMap;
QMap<QString, QString> mPresentIdsMap;
};
class PageCopier
{
public:
void copyPage (const QUrl &fromDir, int fromIndex, const QUrl &toDir, int toIndex)
{
mFromDir = fromDir.toLocalFile();
mToDir = toDir.toLocalFile();
mFromIndex = fromIndex;
mToIndex = toIndex;
QString svgFrom = mFromDir + "/" + svgPageName(fromIndex);
QString svgTo = toDir.toLocalFile() + "/" + svgPageName(toIndex);
QDomDocument dd = createDomFromSvg(svgFrom);
QFile fl(svgTo);
if (!fl.open(QIODevice::WriteOnly)) {
qDebug() << Q_FUNC_INFO << "can't open" << fl.fileName() << "for writing";
return;
}
cureIdsFromSvgDom(dd);
QTextStream str(&fl);
dd.save(str, 0);
fl.close();
qDebug() << Q_FUNC_INFO;
}
private:
void cureIdsFromSvgDom(const QDomDocument &dom)
{
Q_ASSERT(!dom.isNull());
QDomElement nextElement = dom.documentElement().firstChildElement();
while (!nextElement.isNull( )) {
qDebug() << "Tag name of the next parsed element is" << nextElement.tagName();
QString nextTag = nextElement.tagName();
cureFromText(nextTag, nextElement);
nextElement = nextElement.nextSiblingElement();
}
}
void cureFromText(const QString &tagName, QDomElement element)
{
if (tagName == tVideo
|| tagName == tAudio
|| tagName == tImage) {
QString newRelative = cureNCopy(element.attribute(aHref));
element.setAttribute(aHref, newRelative);
if (element.hasAttribute(aActionMedia)) {
QString newActionPath = cureNCopy(element.attribute(aActionMedia));
element.setAttribute(aActionMedia, newActionPath);
}
} else if (tagName == tForeignObject) {
//Pdf object is a special case. Detect if it ends with #reference
QString reqExt = element.attribute(aReqExt);
if (reqExt == vReqExt) { //pdf reference
QString ref = element.attribute(aHref);
if (ref.isEmpty()) {
return;
}
ref.replace(QRegExp("^(.*pdf\\#page\\=).*$"), QString("\\1%1").arg(mToIndex));
return;
}
QString type = element.attribute(aType);
if (type == vText) { // We don't have to care of the text object
if (element.hasAttribute(aActionMedia)) {
QString newRelative = cureNCopy(element.attribute(aActionMedia));
element.setAttribute(aActionMedia, newRelative);
}
return;
}
QString newRelative = cureNCopy(element.attribute(aSrc));
element.setAttribute(aSrc, newRelative);
} else if (tagName == tTeacherGuide) {
QDomElement nMediaElement = element.firstChildElement(tMedia);
while (!nMediaElement.isNull()) {
QString newRelative = cureNCopy(nMediaElement.attribute(aRelativePath));
nMediaElement.setAttribute(aRelativePath, newRelative);
nMediaElement = nMediaElement.nextSiblingElement(tMedia);
}
}
}
QString cureNCopy(const QString &relativePath)
{
QString relative = relativePath;
QUuid newUuid = QUuid::createUuid();
QString newPath = relative.replace(QRegExp("\\{.*\\}"), newUuid.toString());
cp_rf(mFromDir + "/" + relativePath, mToDir + "/" + newPath);
return newPath;
}
private:
QString mFromDir;
QString mToDir;
int mFromIndex;
int mToIndex;
};
class UBForeighnObjectsHandlerPrivate {
UBForeighnObjectsHandlerPrivate(UBForeighnObjectsHandler *pq)
: q(pq)
{
}
public:
void cure(const QUrl &dir)
{
Cleaner *cleaner = new Cleaner;
cleaner->cure(dir);
delete cleaner;
cleaner = 0;
}
void copyPage (const QUrl &fromDir, int fromIndex, const QUrl &toDir, int toIndex)
{
PageCopier *copier = new PageCopier;
copier->copyPage(fromDir, fromIndex, toDir, toIndex);
delete copier;
copier = 0;
}
private:
UBForeighnObjectsHandler *q;
friend class UBForeighnObjectsHandler;
};
UBForeighnObjectsHandler::UBForeighnObjectsHandler()
: d(new UBForeighnObjectsHandlerPrivate(this))
{
}
UBForeighnObjectsHandler::~UBForeighnObjectsHandler()
{
delete d;
}
void UBForeighnObjectsHandler::cure(const QList<QUrl> &dirs)
{
foreach (QUrl dir, dirs) {
cure(dir);
}
}
void UBForeighnObjectsHandler::cure(const QUrl &dir)
{
d->cure(dir);
}
void UBForeighnObjectsHandler::copyPage(const QUrl &fromDir, int fromIndex, const QUrl &toDir, int toIndex)
{
d->copyPage(fromDir, fromIndex, toDir, toIndex);
}

@ -0,0 +1,49 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBFOREIGHNOBJECTSHANDLER_H
#define UBFOREIGHNOBJECTSHANDLER_H
#include <QList>
#include <QUrl>
#include <algorithm>
class UBForeighnObjectsHandlerPrivate;
class UBForeighnObjectsHandler
{
public:
UBForeighnObjectsHandler();
~UBForeighnObjectsHandler();
void cure(const QList<QUrl> &dirs);
void cure(const QUrl &dir);
void copyPage(const QUrl &fromDir, int fromIndex,
const QUrl &toDir, int toIndex);
private:
UBForeighnObjectsHandlerPrivate *d;
friend class UBForeighnObjectsHandlerPrivate;
};
#endif // UBFOREIGHNOBJECTSHANDLER_H

File diff suppressed because it is too large Load Diff

@ -1,32 +1,26 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBPERSISTENCEMANAGER_H_
#define UBPERSISTENCEMANAGER_H_
@ -34,11 +28,13 @@
#include "UBSceneCache.h"
#include "UBPersistenceWorker.h"
class QDomNode;
class QDomElement;
class UBDocument;
class UBDocumentProxy;
class UBGraphicsScene;
class UBDocumentTreeNode;
class UBDocumentTreeModel;
class UBPersistenceManager : public QObject
{
@ -57,16 +53,40 @@ class UBPersistenceManager : public QObject
static const QString videoDirectory;
static const QString audioDirectory;
static const QString widgetDirectory;
static const QString teacherGuideDirectory;
static void shiftPagesToStartWithTheZeroOne(QString persistencePath);
static const QString fileDirectory; // Issue 1683 (Evolution) - AOU - 20131206
static const QString myDocumentsName;
static const QString modelsName;
static const QString untitledDocumentsName;
static const QString fFolders;
static const QString tFolder;
static const QString aName;
static UBPersistenceManager* persistenceManager();
static void destroy();
virtual UBDocumentProxy* createDocument(const QString& pGroupName = "", const QString& pName = "", bool withEmptyPage = true);
virtual UBDocumentProxy* createDocumentFromDir(const QString& pDocumentDirectory, const QString& pGroupName = "", const QString& pName = "");
virtual void persistDocumentMetadata(UBDocumentProxy* pDocumentProxy, bool forceImmediateSaving = false);
virtual UBDocumentProxy* createDocument(const QString& pGroupName = ""
, const QString& pName = ""
, bool withEmptyPage = true
, QString directory =QString()
, int pageCount = 0
, bool promptDialogIfExists = false);
virtual UBDocumentProxy *createNewDocument(const QString& pGroupName = ""
, const QString& pName = ""
, bool withEmptyPage = true
, QString directory =QString()
, int pageCount = 0
, bool promptDialogIfExists = false);
virtual UBDocumentProxy* createDocumentFromDir(const QString& pDocumentDirectory
, const QString& pGroupName = ""
, const QString& pName = ""
, bool withEmptyPage = false
, bool addTitlePage = false
, bool promptDialogIfExists = false);
virtual UBDocumentProxy* persistDocumentMetadata(UBDocumentProxy* pDocumentProxy);
virtual UBDocumentProxy* duplicateDocument(UBDocumentProxy* pDocumentProxy);
@ -76,19 +96,24 @@ class UBPersistenceManager : public QObject
virtual void duplicateDocumentScene(UBDocumentProxy* pDocumentProxy, int index);
virtual void copyDocumentScene(UBDocumentProxy *from, int fromIndex, UBDocumentProxy *to, int toIndex);
virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy,
UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup = false, bool forceImmediateSaving = false);
UBGraphicsScene* pScene, const int pSceneIndex);
virtual UBGraphicsScene* createDocumentSceneAt(UBDocumentProxy* pDocumentProxy, int index, bool useUndoRedoStack = true);
virtual void insertDocumentSceneAt(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* scene, int index);
virtual void insertDocumentSceneAt(UBDocumentProxy* pDocumentProxy, UBGraphicsScene* scene, int index, bool persist = true);
virtual void moveSceneToIndex(UBDocumentProxy* pDocumentProxy, int source, int target);
virtual UBGraphicsScene* loadDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex, bool cacheNeighboringScenes = true);
virtual UBGraphicsScene* loadDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex);
UBGraphicsScene *getDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex) {return mSceneCache.value(pDocumentProxy, sceneIndex);}
void reassignDocProxy(UBDocumentProxy *newDocument, UBDocumentProxy *oldDocument);
QList<QPointer<UBDocumentProxy> > documentProxies;
// QList<QPointer<UBDocumentProxy> > documentProxies;
UBDocumentTreeNode *mDocumentTreeStructure;
UBDocumentTreeModel *mDocumentTreeStructureModel;
virtual QStringList allShapes();
virtual QStringList allGips();
@ -101,7 +126,9 @@ class UBPersistenceManager : public QObject
bool addDirectoryContentToDocument(const QString& documentRootFolder, UBDocumentProxy* pDocument);
virtual UBDocumentProxy* documentByUuid(const QUuid& pUuid);
void createDocumentProxiesStructure(bool interactive = false);
void createDocumentProxiesStructure(const QFileInfoList &contentInfo, bool interactive = false);
QDialog::DialogCode processInteractiveReplacementDialog(UBDocumentProxy *pProxy);
QStringList documentSubDirectories()
{
@ -114,7 +141,21 @@ class UBPersistenceManager : public QObject
bool addGraphicsWidgetToDocument(UBDocumentProxy *mDocumentProxy, QString path, QUuid objectUuid, QString& destinationPath);
bool addFileToDocument(UBDocumentProxy* pDocumentProxy, QString path, const QString& subdir, QUuid objectUuid, QString& destinationPath, QByteArray* data = NULL);
bool mayHaveVideo(UBDocumentProxy* pDocumentProxy);
bool mayHaveAudio(UBDocumentProxy* pDocumentProxy);
bool mayHavePDF(UBDocumentProxy* pDocumentProxy);
bool mayHaveSVGImages(UBDocumentProxy* pDocumentProxy);
bool mayHaveWidget(UBDocumentProxy* pDocumentProxy);
QString adjustDocumentVirtualPath(const QString &str);
void closing();
bool isSceneInCached(UBDocumentProxy *proxy, int index) const;
signals:
void proxyListChanged();
void documentCreated(UBDocumentProxy* pDocumentProxy);
void documentMetadataChanged(UBDocumentProxy* pDocumentProxy);
void documentWillBeDeleted(UBDocumentProxy* pDocumentProxy);
@ -122,50 +163,31 @@ class UBPersistenceManager : public QObject
void documentSceneCreated(UBDocumentProxy* pDocumentProxy, int pIndex);
void documentSceneWillBeDeleted(UBDocumentProxy* pDocumentProxy, int pIndex);
private:
private:
int sceneCount(const UBDocumentProxy* pDocumentProxy);
static QStringList getSceneFileNames(const QString& folder);
QList<QPointer<UBDocumentProxy> > allDocumentProxies();
void renamePage(UBDocumentProxy* pDocumentProxy,
const int sourceIndex, const int targetIndex);
const int sourceIndex, const int targetIndex);
void copyPage(UBDocumentProxy* pDocumentProxy,
const int sourceIndex, const int targetIndex);
const int sourceIndex, const int targetIndex);
void generatePathIfNeeded(UBDocumentProxy* pDocumentProxy);
void checkIfDocumentRepositoryExists();
UBSceneCache mSceneCache;
void saveFoldersTreeToXml(QXmlStreamWriter &writer, const QModelIndex &parentIndex);
void loadFolderTreeFromXml(const QString &path, const QDomElement &element);
QStringList mDocumentSubDirectories;
QString xmlFolderStructureFilename;
UBSceneCache mSceneCache;
QStringList mDocumentSubDirectories;
QMutex mDeletedListMutex;
bool mHasPurgedDocuments;
QList<UBDocumentProxy*> mDocumentCreatedDuringSession;
QString mDocumentRepositoryPath;
UBPersistenceWorker* mWorker;
QThread* mThread;
bool mIsWorkerFinished;
bool mIsApplicationClosing;
QString mFoldersXmlStorageName;
private slots:
void documentRepositoryChanged(const QString& path);
void errorString(QString error);
void onSceneLoaded(QByteArray,UBDocumentProxy*,int);
void onWorkerFinished();
void onScenePersisted(UBGraphicsScene* scene);
void onMetadataPersisted(UBDocumentProxy* proxy);
};

@ -190,6 +190,33 @@ void UBSceneCache::moveScene(UBDocumentProxy* proxy, int sourceIndex, int target
}
void UBSceneCache::reassignDocProxy(UBDocumentProxy *newDocument, UBDocumentProxy *oldDocument)
{
if (!newDocument || !oldDocument) {
return;
}
if (newDocument->pageCount() != oldDocument->pageCount()) {
return;
}
if (!QFileInfo(oldDocument->persistencePath()).exists()) {
return;
}
for (int i = 0; i < oldDocument->pageCount(); i++) {
UBSceneCacheID sourceKey(oldDocument, i);
UBGraphicsScene *currentScene = value(sourceKey);
if (currentScene) {
currentScene->setDocument(newDocument);
}
mCachedKeyFIFO.removeAll(sourceKey);
int count = QHash<UBSceneCacheID, UBGraphicsScene*>::remove(sourceKey);
mCachedSceneCount -= count;
insert(newDocument, i, currentScene);
}
}
void UBSceneCache::shiftUpScenes(UBDocumentProxy* proxy, int startIncIndex, int endIncIndex)
{

@ -98,6 +98,8 @@ class UBSceneCache : public QHash<UBSceneCacheID, UBGraphicsScene*>
void moveScene(UBDocumentProxy* proxy, int sourceIndex, int targetIndex);
void reassignDocProxy(UBDocumentProxy *newDocument, UBDocumentProxy *oldDocument);
void shiftUpScenes(UBDocumentProxy* proxy, int startIncIndex, int endIncIndex);

@ -15,7 +15,8 @@ HEADERS += src/core/UB.h \
src/core/UBDownloadThread.h \
src/core/UBOpenSankoreImporter.h \
src/core/UBTextTools.h \
src/core/UBPersistenceWorker.h
src/core/UBPersistenceWorker.h \
$$PWD/UBForeignObjectsHandler.h
SOURCES += src/core/main.cpp \
src/core/UBApplication.cpp \
@ -33,4 +34,5 @@ SOURCES += src/core/main.cpp \
src/core/UBDownloadThread.cpp \
src/core/UBOpenSankoreImporter.cpp \
src/core/UBTextTools.cpp \
src/core/UBPersistenceWorker.cpp
src/core/UBPersistenceWorker.cpp \
$$PWD/UBForeignObjectsHandler.cpp

@ -0,0 +1,90 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QPainter>
#include <QDebug>
#include "UBActionableWidget.h"
#include "core/memcheck.h"
UBActionableWidget::UBActionableWidget(QWidget *parent, const char *name):QWidget(parent)
, mShowActions(false)
{
setObjectName(name);
mActions.clear();
mCloseButtons.setIcon(QIcon(QPixmap(":images/close.svg")));
mCloseButtons.setGeometry(0, 0, 2*ACTIONSIZE, ACTIONSIZE);
mCloseButtons.setVisible(false);
connect(&mCloseButtons, SIGNAL(clicked()), this, SLOT(onCloseClicked()));
}
UBActionableWidget::~UBActionableWidget()
{
}
void UBActionableWidget::addAction(eAction act)
{
if(!mActions.contains(act)){
mActions << act;
}
}
void UBActionableWidget::removeAction(eAction act)
{
if(mActions.contains(act)){
mActions.remove(mActions.indexOf(act));
}
}
void UBActionableWidget::removeAllActions()
{
mActions.clear();
}
void UBActionableWidget::setActionsVisible(bool bVisible)
{
if(!mActions.empty() && mActions.contains(eAction_Close)){
mCloseButtons.setVisible(bVisible);
}
}
void UBActionableWidget::onCloseClicked()
{
emit close(this);
}
void UBActionableWidget::setActionsParent(QWidget *parent)
{
if(mActions.contains(eAction_Close)){
mCloseButtons.setParent(parent);
}
}
void UBActionableWidget::unsetActionsParent()
{
if(mActions.contains(eAction_Close)){
mCloseButtons.setParent(this);
}
}

@ -0,0 +1,68 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBACTIONABLEWIDGET_H
#define UBACTIONABLEWIDGET_H
#include <QWidget>
#include <QPaintEvent>
#include <QToolButton>
#include <QPushButton>
#define ACTIONSIZE 16
typedef enum{
eAction_Close,
eAction_MoveUp,
eAction_MoveDown
}eAction;
class UBActionableWidget : public QWidget
{
Q_OBJECT
public:
UBActionableWidget(QWidget* parent=0, const char* name="UBActionableWidget");
~UBActionableWidget();
void addAction(eAction act);
void removeAction(eAction act);
void removeAllActions();
void setActionsVisible(bool bVisible);
signals:
void close(QWidget* w);
protected:
void setActionsParent(QWidget* parent);
void unsetActionsParent();
QVector<eAction> mActions;
QPushButton mCloseButtons;
private slots:
void onCloseClicked();
private:
bool mShowActions;
};
#endif // UBACTIONABLEWIDGET_H

@ -0,0 +1,212 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "UBGraphicsItemAction.h"
#include "core/UBApplication.h"
#include "core/UBPersistenceManager.h"
#include "board/UBBoardController.h"
#include "web/UBWebController.h"
#include "document/UBDocumentController.h"
#include "document/UBDocumentProxy.h"
#include "document/UBDocumentContainer.h"
#include "board/UBBoardController.h"
UBGraphicsItemAction::UBGraphicsItemAction(eUBGraphicsItemLinkType linkType, QObject *parent) :
QObject(parent)
{
mLinkType = linkType;
}
void UBGraphicsItemAction::actionRemoved()
{
//NOOP
}
UBGraphicsItemPlayAudioAction::UBGraphicsItemPlayAudioAction(QString audioFile, bool onImport, QObject *parent) :
UBGraphicsItemAction(eLinkToAudio,parent)
, mMediaObject(0)
, mIsLoading(true)
{
Q_ASSERT(audioFile.length() > 0);
if(onImport){
QString extension = QFileInfo(audioFile).completeSuffix();
QString destDir = UBApplication::boardController->selectedDocument()->persistencePath() + "/" + UBPersistenceManager::audioDirectory;
QString destFile = destDir + "/" + QUuid::createUuid().toString() + "." + extension;
if(!QDir(destDir).exists())
QDir(UBApplication::boardController->selectedDocument()->persistencePath()).mkdir(destDir);
//explanation : the audioFile could be relative. The method copy will return false so a second try is done adding
// the document file path
if(!QFile(audioFile).copy(destFile))
QFile(UBApplication::boardController->selectedDocument()->persistencePath() + "/" + audioFile).copy(destFile);
mAudioPath = destFile;
mFullPath = destFile;
}
else
{
//On import don't recreate the file
mAudioPath = audioFile;
mFullPath = mAudioPath;
}
mAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
mMediaObject = new Phonon::MediaObject(this);
Phonon::createPath(mMediaObject, mAudioOutput);
mMediaObject->setCurrentSource(Phonon::MediaSource(mAudioPath));
}
UBGraphicsItemPlayAudioAction::UBGraphicsItemPlayAudioAction() :
UBGraphicsItemAction(eLinkToAudio,NULL)
, mMediaObject(0)
, mIsLoading(true)
{
}
void UBGraphicsItemPlayAudioAction::setPath(QString audioPath)
{
Q_ASSERT(audioPath.length() > 0);
mAudioPath = audioPath;
mFullPath = mAudioPath;
mAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
mMediaObject = new Phonon::MediaObject(this);
Phonon::createPath(mMediaObject, mAudioOutput);
mMediaObject->setCurrentSource(Phonon::MediaSource(mAudioPath));
}
QString UBGraphicsItemPlayAudioAction::fullPath()
{
return mFullPath;
}
UBGraphicsItemPlayAudioAction::~UBGraphicsItemPlayAudioAction()
{
if(!mMediaObject && mMediaObject->state() == Phonon::PlayingState)
mMediaObject->stop();
}
void UBGraphicsItemPlayAudioAction::onSourceHide()
{
if(mMediaObject && mMediaObject->state() == Phonon::PlayingState){
mMediaObject->stop();
}
}
void UBGraphicsItemPlayAudioAction::play()
{
if(mMediaObject->state() == Phonon::PlayingState){
mMediaObject->stop();
}
mMediaObject->seek(0);
mMediaObject->play();
}
QStringList UBGraphicsItemPlayAudioAction::save()
{
//Another hack
if(UBApplication::documentController && UBApplication::documentController->selectedDocument()){
QString documentPath = UBApplication::documentController->selectedDocument()->persistencePath() + "/";
return QStringList() << QString("%1").arg(eLinkToAudio) << mAudioPath.replace(documentPath,"");
}
else{
int index = mAudioPath.indexOf("/audios/");
QString relativePath = mAudioPath.remove(0,index + 1);
return QStringList() << QString("%1").arg(eLinkToAudio) << relativePath;
}
}
void UBGraphicsItemPlayAudioAction::actionRemoved()
{
QFile(mAudioPath).remove();
}
UBGraphicsItemMoveToPageAction::UBGraphicsItemMoveToPageAction(eUBGraphicsItemMovePageAction actionType, int page, QObject* parent) :
UBGraphicsItemAction(eLinkToPage,parent)
{
mActionType = actionType;
mPage = page;
}
void UBGraphicsItemMoveToPageAction::play()
{
UBBoardController* boardController = UBApplication::boardController;
switch (mActionType) {
case eMoveToFirstPage:
boardController->firstScene();
break;
case eMoveToLastPage:
boardController->lastScene();
break;
case eMoveToPreviousPage:
boardController->previousScene();
break;
case eMoveToNextPage:
boardController->nextScene();
break;
case eMoveToPage:
if(mPage >= 0 && mPage < boardController->pageCount())
boardController->setActiveDocumentScene(mPage);
else
qWarning() << "scene number " << mPage << "ins't accessible anymore";
break;
default:
break;
}
}
QStringList UBGraphicsItemMoveToPageAction::save()
{
return QStringList() << QString("%1").arg(eLinkToPage) << QString("%1").arg(mActionType) << QString("%1").arg(mPage);
}
UBGraphicsItemLinkToWebPageAction::UBGraphicsItemLinkToWebPageAction(QString url, QObject *parent) :
UBGraphicsItemAction(eLinkToWebUrl,parent)
{
if (url.length() > 0)
{
if(!url.startsWith("http://"))
url = "http://" + url;
mUrl = url;
}
else
mUrl = QString();
}
void UBGraphicsItemLinkToWebPageAction::play()
{
if (mUrl.length() > 0)
UBApplication::webController->loadUrl(QUrl(mUrl));
}
QStringList UBGraphicsItemLinkToWebPageAction::save()
{
return QStringList() << QString("%1").arg(eLinkToWebUrl) << mUrl;
}

@ -0,0 +1,124 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBGRAPHICSITEMSACTIONS_H
#define UBGRAPHICSITEMSACTIONS_H
#include <QObject>
#include <phonon>
enum eUBGraphicsItemMovePageAction {
eMoveToFirstPage = 0,
eMoveToLastPage,
eMoveToPreviousPage,
eMoveToNextPage,
eMoveToPage
} ;
enum eUBGraphicsItemLinkType
{
eLinkToAudio = 0,
eLinkToPage,
eLinkToWebUrl
};
class UBGraphicsItemAction : public QObject
{
Q_OBJECT
public:
UBGraphicsItemAction(eUBGraphicsItemLinkType linkType,QObject* parent = 0);
virtual void play() = 0;
virtual QStringList save() = 0;
virtual void actionRemoved();
virtual QString path() {return "";}
eUBGraphicsItemLinkType linkType() { return mLinkType;}
signals:
public slots:
private:
eUBGraphicsItemLinkType mLinkType;
};
class UBGraphicsItemPlayAudioAction : public UBGraphicsItemAction
{
Q_OBJECT
public:
UBGraphicsItemPlayAudioAction(QString audioFile, bool onImport = true, QObject* parent = 0);
UBGraphicsItemPlayAudioAction();
~UBGraphicsItemPlayAudioAction();
void play();
QStringList save();
void actionRemoved();
QString path() {return mAudioPath;}
void setPath(QString audioPath);
QString fullPath();
public slots:
void onSourceHide();
private:
QString mAudioPath;
Phonon::MediaObject *mMediaObject;
Phonon::AudioOutput *mAudioOutput;
bool mIsLoading;
QString mFullPath;
};
class UBGraphicsItemMoveToPageAction : public UBGraphicsItemAction
{
Q_OBJECT
public:
UBGraphicsItemMoveToPageAction(eUBGraphicsItemMovePageAction actionType, int page = 0, QObject* parent = 0);
void play();
QStringList save();
int page(){return mPage;}
eUBGraphicsItemMovePageAction actionType(){return mActionType;}
private:
eUBGraphicsItemMovePageAction mActionType;
int mPage;
};
class UBGraphicsItemLinkToWebPageAction : public UBGraphicsItemAction
{
Q_OBJECT
public:
UBGraphicsItemLinkToWebPageAction(QString url, QObject* parent = 0);
void play();
QStringList save();
QString url(){return mUrl;}
private:
QString mUrl;
};
#endif // UBGRAPHICSITEMSACTIONS_H

@ -0,0 +1,368 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#include "core/UBApplication.h"
#include "globals/UBGlobals.h"
#include "UBMediaWidget.h"
#include "core/memcheck.h"
/**
* \brief Constructor
* @param type as the media type
* @param parent as the parent widget
* @param name as the object name
*/
UBMediaWidget::UBMediaWidget(eMediaType type, QWidget *parent, const char *name):UBActionableWidget(parent, name)
, mpMediaObject(NULL)
, mpVideoWidget(NULL)
, mpAudioOutput(NULL)
, mpLayout(NULL)
, mpSeekerLayout(NULL)
, mpPlayStopButton(NULL)
, mpPauseButton(NULL)
, mpSlider(NULL)
, mAutoUpdate(false)
, mGeneratingThumbnail(false)
, mBorder(5)
, mpMediaContainer(NULL)
, mMediaLayout(NULL)
, mpCover(NULL)
{
SET_STYLE_SHEET();
addAction(eAction_Close);
mType = type;
mpLayout = new QVBoxLayout(this);
setLayout(mpLayout);
mpPlayStopButton = new UBMediaButton(this);
mpPlayStopButton->setPixmap(QPixmap(":images/play.svg"));
mpPauseButton = new UBMediaButton(this);
mpPauseButton->setPixmap(QPixmap(":images/pause.svg"));
mpPauseButton->setEnabled(false);
mpSlider = new QSlider(this);
mpSlider->setOrientation(Qt::Horizontal);
mpSlider->setMinimum(0);
mpSlider->setMaximum(0);
mpSeekerLayout = new QHBoxLayout();
mpSeekerLayout->addWidget(mpPlayStopButton, 0);
mpSeekerLayout->addWidget(mpPauseButton, 0);
mpSeekerLayout->addWidget(mpSlider, 1);
mpSeekerLayout->setContentsMargins(0, 0, 0, 0);
connect(mpPlayStopButton, SIGNAL(clicked()), this, SLOT(onPlayStopClicked()));
connect(mpPauseButton, SIGNAL(clicked()), this, SLOT(onPauseClicked()));
connect(mpSlider, SIGNAL(valueChanged(int)), this, SLOT(onSliderChanged(int)));
}
/**
* \brief Destructor
*/
UBMediaWidget::~UBMediaWidget()
{
unsetActionsParent();
DELETEPTR(mpMediaObject);
DELETEPTR(mpSlider);
DELETEPTR(mpPauseButton);
DELETEPTR(mpPlayStopButton);
DELETEPTR(mpAudioOutput);
DELETEPTR(mpVideoWidget);
DELETEPTR(mpCover);
DELETEPTR(mpMediaContainer);
DELETEPTR(mpSeekerLayout);
DELETEPTR(mpLayout);
}
/**
* \brief Set the media file
* @param filePath as the media file path
*/
void UBMediaWidget::setFile(const QString &filePath)
{
Q_ASSERT("" != filePath);
mFilePath = filePath;
mpMediaObject = new Phonon::MediaObject(this);
mpMediaObject->setTickInterval(TICK_INTERVAL);
connect(mpMediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(onStateChanged(Phonon::State,Phonon::State)));
connect(mpMediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(onTotalTimeChanged(qint64)));
connect(mpMediaObject, SIGNAL(tick(qint64)), this, SLOT(onTick(qint64)));
mpMediaObject->setCurrentSource(Phonon::MediaSource(filePath));
createMediaPlayer();
}
/**
* \brief Get the media type
* @returns the media type
*/
eMediaType UBMediaWidget::mediaType()
{
return mType;
}
void UBMediaWidget::showEvent(QShowEvent* event)
{
if(mType == eMediaType_Audio){
return;
}else{
if(!mpVideoWidget){
mpVideoWidget = new Phonon::VideoWidget(this);
mMediaLayout->addStretch(1);
mMediaLayout->addWidget(mpVideoWidget);
mMediaLayout->addStretch(1);
Phonon::createPath(mpMediaObject, mpVideoWidget);
adaptSizeToVideo();
mpMediaObject->play();
mpMediaObject->stop();
}
QWidget::showEvent(event);
}
}
void UBMediaWidget::hideEvent(QHideEvent* event)
{
if(mpMediaObject->state() == Phonon::PlayingState)
mpMediaObject->stop();
UBActionableWidget::hideEvent(event);
}
/**
* \brief Create the media player
*/
void UBMediaWidget::createMediaPlayer()
{
mpMediaContainer = new QWidget();
mpMediaContainer->setObjectName("UBMediaVideoContainer");
mMediaLayout = new QHBoxLayout();
mpMediaContainer->setLayout(mMediaLayout);
if(eMediaType_Video == mType){
mMediaLayout->setContentsMargins(10, 10, 10, 10);
if(isVisible()){
mpVideoWidget = new Phonon::VideoWidget(this);
mMediaLayout->addStretch(1);
mMediaLayout->addWidget(mpVideoWidget);
mMediaLayout->addStretch(1);
Phonon::createPath(mpMediaObject, mpVideoWidget);
adaptSizeToVideo();
}
mpAudioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
Phonon::createPath(mpMediaObject, mpAudioOutput);
}else if(eMediaType_Audio == mType){
mMediaLayout->setContentsMargins(10, 10, 10, 10);
mpCover = new QLabel(mpMediaContainer);
//mpMediaContainer->setStyleSheet(QString("background: none;"));
setAudioCover(":images/libpalette/soundIcon.svg");
mpCover->setScaledContents(true);
mMediaLayout->addStretch(1);
mMediaLayout->addWidget(mpCover);
mMediaLayout->addStretch(1);
mpAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
Phonon::createPath(mpMediaObject, mpAudioOutput);
}
mpLayout->addWidget(mpMediaContainer, 1);
mpLayout->addLayout(mpSeekerLayout, 0);
setActionsParent(mpMediaContainer);
}
/**
* \brief Adapt the widget size to the video in order to keep the good aspect ratio
*/
void UBMediaWidget::adaptSizeToVideo()
{
if(NULL != mpMediaContainer){
int origW = mpMediaContainer->width();
int origH = mpMediaContainer->height();
int newW = width();
float scaleFactor = (float)origW/(float)newW;
int newH = origH/scaleFactor;
resize(newW, height() + newH);
}
}
/**
* \brief Handle the media state change notification
* @param newState as the new state
* @param oldState as the old state
*/
void UBMediaWidget::onStateChanged(Phonon::State newState, Phonon::State oldState)
{
if(!mGeneratingThumbnail){
if(Phonon::LoadingState == oldState && Phonon::StoppedState == newState){
if(eMediaType_Video == mType){
// We do that here to generate the thumbnail of the video
mGeneratingThumbnail = true;
mpMediaObject->play();
mpMediaObject->pause();
mGeneratingThumbnail = false;
}
}else if(Phonon::PlayingState == oldState && Phonon::PausedState == newState){
mpPlayStopButton->setPixmap(QPixmap(":images/play.svg"));
mpPauseButton->setEnabled(false);
}else if((Phonon::PausedState == oldState && Phonon::PlayingState == newState) ||
(Phonon::StoppedState == oldState && Phonon::PlayingState == newState)){
mpPlayStopButton->setPixmap(QPixmap(":images/stop.svg"));
mpPauseButton->setEnabled(true);
}else if(Phonon::PlayingState == oldState && Phonon::StoppedState == newState){
mpPlayStopButton->setPixmap(QPixmap(":images/play.svg"));
mpPauseButton->setEnabled(false);
mpSlider->setValue(0);
}
}
// if(mType == eMediaType_Video)
// updateView(newState);
}
/**
* \brief Handles the total time change notification
* @param total as the new total time
*/
void UBMediaWidget::onTotalTimeChanged(qint64 total)
{
mpSlider->setMaximum(total);
}
/**
* \brief Handles the tick notification
* @param currentTime as the current time
*/
void UBMediaWidget::onTick(qint64 currentTime)
{
mAutoUpdate = true;
mpSlider->setValue((int)currentTime);
mAutoUpdate = false;
}
/**
* \brief Handles the seeker value change notification
* @param value as the new seeker value
*/
void UBMediaWidget::onSliderChanged(int value)
{
if(!mAutoUpdate){
mpMediaObject->seek(value);
}
}
/**
* \brief Toggle Play-Stop
*/
void UBMediaWidget::onPlayStopClicked()
{
switch(mpMediaObject->state()){
case Phonon::PlayingState:
mpMediaObject->stop();
break;
case Phonon::StoppedState:
case Phonon::PausedState:
mpMediaObject->play();
break;
default:
break;
}
}
/**
* \brief Pause the media
*/
void UBMediaWidget::onPauseClicked()
{
mpMediaObject->pause();
}
/**
* Get the border
* @returns the actual border
*/
int UBMediaWidget::border()
{
return mBorder;
}
/**
* \brief Handles the resize event
* @param ev as the resize event
*/
void UBMediaWidget::resizeEvent(QResizeEvent* ev)
{
Q_UNUSED(ev);
}
/**
* \brief Set the audio cover
* @param coverPath as the cover image file path
*/
void UBMediaWidget::setAudioCover(const QString &coverPath)
{
if(NULL != mpCover){
mpCover->setPixmap(QPixmap(coverPath));
}
}
// -----------------------------------------------------------------------------------------------------------
/**
* \brief Constructor
* @param parent as the parent widget
* @param name as the object name
*/
UBMediaButton::UBMediaButton(QWidget *parent, const char *name):QLabel(parent)
, mPressed(false)
{
setObjectName(name);
resize(UBMEDIABUTTON_SIZE, UBMEDIABUTTON_SIZE);
setStyleSheet(QString("padding:0px 0px 0px 0px; margin:0px 0px 0px 0px;"));
}
/**
* \brief Destructor
*/
UBMediaButton::~UBMediaButton()
{
}
/**
* \brief Handles the mouse press notification
* @param ev as the mouse press event
*/
void UBMediaButton::mousePressEvent(QMouseEvent* ev)
{
Q_UNUSED(ev);
mPressed = true;
}
/**
* \brief Handles the mouse release notification
* @param ev as the mouse release event
*/
void UBMediaButton::mouseReleaseEvent(QMouseEvent* ev)
{
Q_UNUSED(ev);
if(mPressed){
mPressed = false;
emit clicked();
}
}

@ -0,0 +1,133 @@
/*
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* This file is part of Open-Sankoré.
*
* Open-Sankoré 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).
*
* Open-Sankoré 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 Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBMEDIAWIDGET_H
#define UBMEDIAWIDGET_H
#include <QWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QSlider>
#include <QMouseEvent>
#include <QStackedWidget>
#include "UBActionableWidget.h"
#define UBMEDIABUTTON_SIZE 32
#define TICK_INTERVAL 1000
/**
* \brief The media type
*/
typedef enum{
eMediaType_Video,
eMediaType_Audio
}eMediaType;
class UBMediaButton : public QLabel
{
Q_OBJECT
public:
UBMediaButton(QWidget* parent=0, const char* name="UBMediaButton");
~UBMediaButton();
signals:
void clicked();
protected:
void mousePressEvent(QMouseEvent* ev);
void mouseReleaseEvent(QMouseEvent* ev);
private:
/** And indicator of the press event in progress */
bool mPressed;
};
class UBMediaWidget : public UBActionableWidget
{
Q_OBJECT
public:
UBMediaWidget(eMediaType type = eMediaType_Video, QWidget* parent=0, const char* name="UBMediaWidget");
~UBMediaWidget();
void setFile(const QString& filePath);
eMediaType mediaType();
int border();
void setAudioCover(const QString& coverPath);
void setUrl(const QString& url){mUrl = url;}
QString url(){return mUrl;}
protected:
void resizeEvent(QResizeEvent* ev);
void showEvent(QShowEvent* event);
void hideEvent(QHideEvent* event);
/** The current media file path */
QString mFilePath;
private slots:
void onPlayStopClicked();
void onPauseClicked();
void onStateChanged(Phonon::State newState, Phonon::State oldState);
void onTotalTimeChanged(qint64 total);
void onTick(qint64 currentTime);
void onSliderChanged(int value);
private:
void createMediaPlayer();
void adaptSizeToVideo();
/** The current media type */
eMediaType mType;
/** The media object */
Phonon::MediaObject* mpMediaObject;
/** The video renderer */
Phonon::VideoWidget* mpVideoWidget;
/** The audio renderer */
Phonon::AudioOutput* mpAudioOutput;
/** The principal layout of this widget */
QVBoxLayout* mpLayout;
/** The seeker layout */
QHBoxLayout* mpSeekerLayout;
/** The play-stop button */
UBMediaButton* mpPlayStopButton;
/** The pause button */
UBMediaButton* mpPauseButton;
/** The seeker slider */
QSlider* mpSlider;
/** An indicator of the seeker auto update in progress */
bool mAutoUpdate;
/** An indicator of the thumbnail generation in progress */
bool mGeneratingThumbnail;
/** The border */
int mBorder;
/** A widget that will contain the media */
QWidget* mpMediaContainer;
/** The media layout */
QHBoxLayout* mMediaLayout;
/** The audio cover */
QLabel* mpCover;
/** The media url */
QString mUrl;
};
#endif // UBMEDIAWIDGET_H

@ -0,0 +1,10 @@
HEADERS += \
src/customWidgets/UBMediaWidget.h \
src/customWidgets/UBActionableWidget.h \
src/customWidgets/UBGraphicsItemAction.h
SOURCES += \
src/customWidgets/UBMediaWidget.cpp \
src/customWidgets/UBActionableWidget.cpp \
src/customWidgets/UBGraphicsItemAction.cpp

@ -102,6 +102,14 @@ void UBDocumentContainer::addPage(int index)
emit addThumbnailRequired(this, index);
}
void UBDocumentContainer::addPixmapAt(const QPixmap *pix, int index)
{
mDocumentThumbs.insert(index, pix);
emit documentThumbnailsUpdated(this);
}
void UBDocumentContainer::clearThumbPage()
{
qDeleteAll(mDocumentThumbs);

@ -42,6 +42,7 @@ class UBDocumentContainer : public QObject
virtual ~UBDocumentContainer();
void setDocument(UBDocumentProxy* document, bool forceReload = false);
void pureSetDocument(UBDocumentProxy *document) {mCurrentDocument = document;}
UBDocumentProxy* selectedDocument(){return mCurrentDocument;}
int pageCount(){return mCurrentDocument->pageCount();}
@ -56,8 +57,10 @@ class UBDocumentContainer : public QObject
void clearThumbPage();
void initThumbPage();
void addPage(int index);
void addPixmapAt(const QPixmap *pix, int index);
void updatePage(int index);
void addEmptyThumbPage();
void reloadThumbnails();
void insertThumbPage(int index);
@ -69,7 +72,6 @@ class UBDocumentContainer : public QObject
protected:
void deleteThumbPage(int index);
void updateThumbPage(int index);
void reloadThumbnails();
signals:
void documentSet(UBDocumentProxy* document);

File diff suppressed because it is too large Load Diff

@ -1,38 +1,36 @@
/*
* Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM)
* Copyright (C) 2010-2013 Groupement d'Intérêt Public pour l'Education Numérique en Afrique (GIP ENA)
*
* Copyright (C) 2013 Open Education Foundation
* This file is part of Open-Sankoré.
*
* 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
* Open-Sankoré 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,
* Open-Sankoré 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
* 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/>.
* along with Open-Sankoré. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UBDOCUMENTCONTROLLER_H_
#define UBDOCUMENTCONTROLLER_H_
#include <QtGui>
#include <QTreeWidgetItem>
#include "document/UBDocumentContainer.h"
#include "core/UBApplicationController.h"
#include "core/UBApplication.h"
#include "document/UBSortFilterProxyModel.h"
namespace Ui
{
@ -51,13 +49,323 @@ class UBDocumentProxyTreeItem;
class UBMainWindow;
class UBDocumentToolsPalette;
class UBDocumentController : public UBDocumentContainer
class UBDocumentReplaceDialog : public QDialog
{
Q_OBJECT
public:
UBDocumentReplaceDialog(const QString &pIncommingName, const QStringList &pFileList, QWidget *parent = 0, Qt::WindowFlags pFlags = 0);
void setRegexp(const QRegExp pRegExp);
bool validString(const QString &pStr);
void setFileNameAndList(const QString &fileName, const QStringList &pLst);
QString labelTextWithName(const QString &documentName) const;
QString lineEditText() const {return mLineEdit->text();}
signals:
void createNewFolder(QString str);
void closeDialog();
private slots:
void accept();
void reject();
void reactOnTextChanged(const QString &pStr);
private:
QLineEdit *mLineEdit;
QRegExpValidator *mValidator;
QStringList mFileNameList;
QString mIncommingName;
QPushButton *acceptButton;
const QString acceptText;
const QString replaceText;
const QString cancelText;
QLabel *mLabelText;
};
class UBDocumentTreeNode
{
public:
friend class UBDocumentTreeModel;
enum Type {
Catalog = 0
, Document
};
UBDocumentTreeNode(Type pType, const QString &pName, const QString &pDisplayName = QString(), UBDocumentProxy *pProxy = 0);
UBDocumentTreeNode() : mType(Catalog), mParent(0), mProxy(0) {;}
~UBDocumentTreeNode();
QList<UBDocumentTreeNode*> children() const {return mChildren;}
UBDocumentTreeNode *parentNode() {return mParent;}
Type nodeType() const {return mType;}
QString nodeName() const {return mName;}
QString displayName() const {return mDisplayName;}
void setNodeName(const QString &str) {mName = str; mDisplayName = str;}
void addChild(UBDocumentTreeNode *pChild);
void insertChild(int pIndex, UBDocumentTreeNode *pChild);
void moveChild(UBDocumentTreeNode *child, int index, UBDocumentTreeNode *newParent);
void removeChild(int index);
UBDocumentProxy *proxyData() const {return mProxy;}
bool isRoot() {return !mParent;}
bool isTopLevel() {return mParent && !mParent->mParent;}
UBDocumentTreeNode *clone();
QString dirPathInHierarchy();
//issue 1629 - NNE - 20131105 : Add some utility methods
bool findNode(UBDocumentTreeNode *node);
UBDocumentTreeNode *nextSibling();
UBDocumentTreeNode *previousSibling();
//issue 1629 - NNE - 20131105 : END
private:
Type mType;
QString mName;
QString mDisplayName;
UBDocumentTreeNode *mParent;
QList<UBDocumentTreeNode*> mChildren;
QPointer<UBDocumentProxy> mProxy;
};
Q_DECLARE_METATYPE(UBDocumentTreeNode*)
class UBDocumentTreeModel : public QAbstractItemModel {
Q_OBJECT
public:
enum eAncestors {
aMyDocuments
, aUntitledDocuments
, aModel
, aTrash
};
enum eCopyMode {
aReference
, aContentCopy
};
enum eAddItemMode {
aEnd = 0 //Add to the end of the children list
, aDetectPosition //Detect the appropriate position (sorting)
};
enum eDocumentData{
DataNode = Qt::UserRole +1,
CreationDate,
UpdateDate
};
UBDocumentTreeModel(QObject *parent = 0);
~UBDocumentTreeModel();
QModelIndex index(int row, int column, const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
Qt::ItemFlags flags ( const QModelIndex & index ) const;
Qt::DropActions supportedDropActions() const {return Qt::MoveAction | Qt::CopyAction;}
QStringList mimeTypes() const;
QMimeData *mimeData (const QModelIndexList &indexes) const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
bool removeRows(int row, int count, const QModelIndex &parent);
QModelIndex indexForNode(UBDocumentTreeNode *pNode) const;
QPersistentModelIndex persistentIndexForNode(UBDocumentTreeNode *pNode);
// bool insertRow(int row, const QModelIndex &parent);
QPersistentModelIndex copyIndexToNewParent(const QModelIndex &source, const QModelIndex &newParent, eCopyMode pMode = aReference);
//N/C - NNE - 20140411
void copyIndexToNewParent(const QModelIndexList &list, const QModelIndex &newParent, eCopyMode pMode);
void moveIndex(const QModelIndex &what, const QModelIndex &destination);
UBDocumentTreeNode *currentNode() const {return mCurrentNode;} //work around for sorting model.
void setCurrentNode(UBDocumentTreeNode *pNode) {mCurrentNode = pNode;}
QModelIndex currentIndex() {return indexForNode(mCurrentNode);} //index representing a current document
QModelIndex indexForProxy(UBDocumentProxy *pSearch) const;
void setCurrentDocument(UBDocumentProxy *pDocument);
void setRootNode(UBDocumentTreeNode *pRoot);
UBDocumentTreeNode *rootNode() const {return mRootNode;}
UBDocumentProxy *proxyForIndex(const QModelIndex &pIndex) const;
QString virtualDirForIndex(const QModelIndex &pIndex) const;
QString virtualPathForIndex(const QModelIndex &pIndex) const;
QStringList nodeNameList(const QModelIndex &pIndex) const;
bool newNodeAllowed(const QModelIndex &pSelectedIndex) const;
QModelIndex goTo(const QString &dir);
bool inTrash(const QModelIndex &index) const;
bool inModel(const QModelIndex &index) const;
bool inUntitledDocuments(const QModelIndex &index) const;
bool isCatalog(const QModelIndex &index) const {return nodeFromIndex(index)->nodeType() == UBDocumentTreeNode::Catalog;}
bool isDocument(const QModelIndex &index) const {return nodeFromIndex(index)->nodeType() == UBDocumentTreeNode::Document;}
bool isToplevel(const QModelIndex &index) const {return nodeFromIndex(index) ? nodeFromIndex(index)->isTopLevel() : false;}
bool isConstant(const QModelIndex &index) const {return isToplevel(index) || (index == mUntitledDocuments);}
bool isOkToRename(const QModelIndex &index) const {return flags(index) & Qt::ItemIsEditable;}
UBDocumentProxy *proxyData(const QModelIndex &index) const {return nodeFromIndex(index)->proxyData();}
void addDocument(UBDocumentProxy *pProxyData, const QModelIndex &pParent = QModelIndex());
void addNewDocument(UBDocumentProxy *pProxyData, const QModelIndex &pParent = QModelIndex());
void addCatalog(const QString &pName, const QModelIndex &pParent);
QList<UBDocumentProxy*> newDocuments() {return mNewDocuments;}
void markDocumentAsNew(UBDocumentProxy *pDoc) {if (indexForProxy(pDoc).isValid()) mNewDocuments << pDoc;}
void setNewName(const QModelIndex &index, const QString &newName);
QString adjustNameForParentIndex(const QString &pName, const QModelIndex &pIndex);
QPersistentModelIndex myDocumentsIndex() const {return mMyDocuments;}
QPersistentModelIndex modelsIndex() const {return mModels;}
QPersistentModelIndex trashIndex() const {return mTrash;}
QPersistentModelIndex untitledDocumentsIndex() const {return mUntitledDocuments;}
UBDocumentTreeNode *nodeFromIndex(const QModelIndex &pIndex) const;
static bool nodeLessThan(const UBDocumentTreeNode *firstIndex, const UBDocumentTreeNode *secondIndex);
void setHighLighted(const QModelIndex &newHighLighted) {mHighLighted = newHighLighted;}
QModelIndex highLighted() {return mHighLighted;}
//N/C - NNE - 20140407
bool ascendingOrder() const{ return mAscendingOrder; }
QDateTime findNodeDate(UBDocumentTreeNode *node, QString type) const;
bool inMyDocuments(const QModelIndex &index) const;
void moveIndexes(const QModelIndexList &source, const QModelIndex &destination);
//N/C - NNE - 20140407 : END
bool isDescendantOf(const QModelIndex &pPossibleDescendant, const QModelIndex &pPossibleAncestor) const;
signals:
void indexChanged(const QModelIndex &newIndex, const QModelIndex &oldIndex);
void currentIndexMoved(const QModelIndex &newIndex, const QModelIndex &previous); /* Be aware that when you got the signal
"previous" index would have allready been deleted.
check it for "valid" first */
private:
UBDocumentTreeNode *mRootNode;
UBDocumentTreeNode *mCurrentNode;
UBDocumentTreeNode *findProxy(UBDocumentProxy *pSearch, UBDocumentTreeNode *pParent) const;
QModelIndex pIndexForNode(const QModelIndex &parent, UBDocumentTreeNode *pNode) const;
QModelIndex addNode(UBDocumentTreeNode *pFreeNode, const QModelIndex &pParent, eAddItemMode pMode = aDetectPosition);
int positionForParent(UBDocumentTreeNode *pFreeNode, UBDocumentTreeNode *pParentNode);
void fixNodeName(const QModelIndex &source, const QModelIndex &dest);
void updateIndexNameBindings(UBDocumentTreeNode *nd);
QPersistentModelIndex mRoot;
QPersistentModelIndex mMyDocuments;
QPersistentModelIndex mModels;
QPersistentModelIndex mTrash;
QPersistentModelIndex mUntitledDocuments;
QList<UBDocumentProxy*> mNewDocuments;
QModelIndex mHighLighted;
//N/C - NNE - 20140407
bool mAscendingOrder;
QDateTime findCatalogUpdatedDate(UBDocumentTreeNode *node) const;
QDateTime findCatalogCreationDate(UBDocumentTreeNode *node) const;
//N/C - NNE - 20140407 : END
};
class UBDocumentTreeMimeData : public QMimeData
{
Q_OBJECT
public:
QList<QModelIndex> indexes() const {return mIndexes;}
void setIndexes (const QList<QModelIndex> &pIndexes) {mIndexes = pIndexes;}
private:
QList<QModelIndex> mIndexes;
};
class UBDocumentTreeView : public QTreeView
{
Q_OBJECT
friend class UBDocumentTreeWidget;
public:
UBDocumentTreeView (QWidget *parent = 0);
//N/C - NNE - 20140404
QModelIndex mapIndexToSource(const QModelIndex &index);
QModelIndexList mapIndexesToSource(const QModelIndexList &indexes);
public slots:
void setSelectedAndExpanded(const QModelIndex &pIndex, bool pExpand = true);
void onModelIndexChanged(const QModelIndex &pNewIndex, const QModelIndex &pOldIndex);
void hSliderRangeChanged(int min, int max);
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
void paintEvent(QPaintEvent *event);
UBDocumentTreeModel *fullModel() {return qobject_cast<UBDocumentTreeModel*>(model());}
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
private:
bool isAcceptable(const QModelIndex &dragIndex, const QModelIndex &atIndex);
Qt::DropAction acceptableAction(const QModelIndex &dragIndex, const QModelIndex &atIndex);
void updateIndexEnvirons(const QModelIndex &index);
};
class UBDocumentTreeItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
UBDocumentTreeItemDelegate(QObject *parent = 0);
private slots:
void commitAndCloseEditor();
void processChangedText(const QString &str) const;
bool validateString(const QString &str) const;
protected:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex &index) const;
private:
mutable QStringList mExistingFileNames;
};
class UBDocumentController : public UBDocumentContainer
{
Q_OBJECT
public:
enum DeletionType {
MoveToTrash = 0
, CompleteDelete
, EmptyFolder
, EmptyTrash
, DeletePage
, NoDeletion
};
enum LastSelectedElementType
{
None = 0, Folder, Document, Page
};
enum SortOrder
{
ASC = 0,
DESC
};
enum SortKind
{
Reset = 0,
CreationDate,
UpdateDate,
Alphabetical
};
UBDocumentController(UBMainWindow* mainWindow);
virtual ~UBDocumentController();
@ -68,22 +376,64 @@ class UBDocumentController : public UBDocumentContainer
void deletePages(QList<QGraphicsItem*> itemsToDelete);
int getSelectedItemIndex();
bool pageCanBeMovedUp(int page);
bool pageCanBeMovedDown(int page);
bool pageCanBeDuplicated(int page);
bool pageCanBeDeleted(int page);
QString documentTrashGroupName(){ return mDocumentTrashGroupName;}
QString defaultDocumentGroupName(){ return mDefaultDocumentGroupName;}
void setDocument(UBDocumentProxy *document, bool forceReload = false);
QModelIndex firstSelectedTreeIndex();
UBDocumentProxy *firstSelectedTreeProxy();
inline DeletionType deletionTypeForSelection(LastSelectedElementType pTypeSelection
, const QModelIndex &selectedIndex
, UBDocumentTreeModel *docModel) const;
bool firstSceneSelected() const;
QWidget *mainWidget() const {return mDocumentWidget;}
//issue 1629 - NNE - 20131212
/**
* Check if the current view will be deleted. If it' true,
* this function assures a view will be always selected, even if
* no view is availaible by creating a new one.
*
* \param index The index that will be deleted.
* \param docModel The tree model which represents the organisation of the document hierarchy
*
* \return True if the index passed in argument was the current view, false otherwise.
*/
void moveToTrash(QModelIndex &index, UBDocumentTreeModel* docModel);
QModelIndex mapIndexToSource(const QModelIndex &index);
QModelIndexList mapIndexesToSource(const QModelIndexList &indexes);
void sortDocuments(int kind, int order);
void moveIndexesToTrash(const QModelIndexList &list, UBDocumentTreeModel *docModel);
QModelIndex findPreviousSiblingNotSelected(const QModelIndex &index, QItemSelectionModel *selectionModel);
QModelIndex findNextSiblingNotSelected(const QModelIndex &index, QItemSelectionModel *selectionModel);
bool parentIsSelected(const QModelIndex& child, QItemSelectionModel *selectionModel);
signals:
void exportDone();
public slots:
void createNewDocument();
//issue 1629 - NNE - 20131105
void createNewDocumentInUntitledFolder();
void createNewDocumentGroup();
void deleteSelectedItem();
void emptyFolder(const QModelIndex &index, DeletionType pDeletionType = MoveToTrash);
void deleteIndexAndAssociatedData(const QModelIndex &pIndex);
void renameSelectedItem();
void openSelectedItem();
void duplicateSelectedItem();
void importFile();
void moveSceneToIndex(UBDocumentProxy* proxy, int source, int target);
void selectDocument(UBDocumentProxy* proxy, bool setAsCurrentDocument = true);
void selectDocument(UBDocumentProxy* proxy, bool setAsCurrentDocument = true, const bool onImport = false);
void show();
void hide();
void showMessage(const QString& message, bool showSpinningWheel = false);
@ -93,22 +443,28 @@ class UBDocumentController : public UBDocumentContainer
void copy();
void paste();
void focusChanged(QWidget *old, QWidget *current);
void updateActions();
void updateExportSubActions(const QModelIndex &selectedIndex);
void currentIndexMoved(const QModelIndex &newIndex, const QModelIndex &PreviousIndex);
//N/C - NNE - 20140403
void onSortKindChanged(int index);
void onSortOrderChanged(int index);
void collapseAll();
void expandAll();
protected:
protected:
virtual void setupViews();
virtual void setupToolbar();
void setupPalettes();
bool isOKToOpenDocument(UBDocumentProxy* proxy);
UBDocumentProxy* selectedDocumentProxy();
QList<UBDocumentProxy*> selectedProxies();
QModelIndexList selectedTreeIndexes();
UBDocumentProxyTreeItem* selectedDocumentProxyTreeItem();
UBDocumentGroupTreeItem* selectedDocumentGroupTreeItem();
QStringList allGroupNames();
enum LastSelectedElementType
{
None = 0, Folder, Document, Page, Multiple
};
LastSelectedElementType mSelectionType;
private:
@ -125,45 +481,45 @@ class UBDocumentController : public UBDocumentContainer
UBDocumentToolsPalette *mToolsPalette;
bool mToolsPalettePositionned;
UBDocumentGroupTreeItem* mTrashTi;
QList<QTreeWidgetItem*> mCurrentSelection;
void moveDocumentToTrash(UBDocumentGroupTreeItem* groupTi, UBDocumentProxyTreeItem *proxyTi);
void moveFolderToTrash(UBDocumentGroupTreeItem* groupTi);
QString mDocumentTrashGroupName;
QString mDefaultDocumentGroupName;
void selectADocumentOnTrashingSelectedOne(UBDocumentGroupTreeItem* groupTi,UBDocumentProxyTreeItem *proxyTi);
void selectFirstDocumentInList();
void selectATreeItemOnMultipleTrashing(bool selectNewCurrentDocument = false);
void moveDocumentToTrash(UBDocumentGroupTreeItem* groupTi, UBDocumentProxyTreeItem *proxyTi, bool selectNewDocument);
void moveFolderToTrash(UBDocumentGroupTreeItem* groupTi);
void emptyTrash(bool showConfirmationDialog);
void deleteTreeItem(QTreeWidgetItem * item, bool showConfirmationDialog, bool selectNewDocument);
UBDocumentProxy *mCurrentTreeDocument;
bool mCurrentIndexMoved;
void updateCurrentSelection();
bool multipleSelection();
bool isDocumentInTrash(UBDocumentProxyTreeItem * document);
bool isCurrentSelectionInTrash();
LastSelectedElementType itemType(QTreeWidgetItem * item);
UBSortFilterProxyModel *mSortFilterProxyModel;
//N/C - NNE - 20140407
bool mUserHasChangedSortOrder;
public slots:
void TreeViewSelectionChanged(const QModelIndex &current, const QModelIndex &previous);
void TreeViewSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
private slots:
private slots:
void documentZoomSliderValueChanged (int value);
void loadDocumentProxies();
void itemSelectionChanged();
void itemSelectionChanged(LastSelectedElementType newSelection);
void exportDocument();
void itemChanged(QTreeWidgetItem * item, int column);
void exportDocumentSet();
void thumbnailViewResized();
void pageSelectionChanged();
void selectionChanged();
void documentSceneChanged(UBDocumentProxy* proxy, int pSceneIndex);
void pageDoubleClicked(QGraphicsItem* item, int index);
void thumbnailPageDoubleClicked(QGraphicsItem* item, int index);
void pageClicked(QGraphicsItem* item, int index);
void addToDocument();
void addDocumentInTree(UBDocumentProxy* pDocument);
void updateDocumentInTree(UBDocumentProxy* pDocument);
void addFolderOfImages();
void addFileToDocument();
void addImages();
void refreshDocumentThumbnailsView(UBDocumentContainer* source);
};
#endif /* UBDOCUMENTCONTROLLER_H_ */

@ -46,6 +46,15 @@ UBDocumentProxy::UBDocumentProxy()
init();
}
UBDocumentProxy::UBDocumentProxy(const UBDocumentProxy &rValue) :
QObject()
{
mPersistencePath = rValue.mPersistencePath;
mMetaDatas = rValue.mMetaDatas;
mIsModified = rValue.mIsModified;
mPageCount = rValue.mPageCount;
}
UBDocumentProxy::UBDocumentProxy(const QString& pPersistancePath)
: mPageCount(0)
@ -70,6 +79,10 @@ void UBDocumentProxy::init()
setDefaultDocumentSize(UBSettings::settings()->pageSize->get().toSize());
}
bool UBDocumentProxy::theSameDocument(UBDocumentProxy *proxy)
{
return proxy && mPersistencePath == proxy->mPersistencePath;
}
UBDocumentProxy::~UBDocumentProxy()
{

@ -47,11 +47,13 @@ class UBDocumentProxy : public QObject
public:
UBDocumentProxy();
UBDocumentProxy(const UBDocumentProxy &rValue);
UBDocumentProxy(const QString& pPersistencePath);
virtual ~UBDocumentProxy();
UBDocumentProxy * deepCopy() const;
bool theSameDocument(UBDocumentProxy *proxy);
QString persistencePath() const;

@ -0,0 +1,25 @@
#include "UBSortFilterProxyModel.h"
#include "UBDocumentController.h"
UBSortFilterProxyModel::UBSortFilterProxyModel():
QSortFilterProxyModel()
{
setDynamicSortFilter(true);
setSortCaseSensitivity(Qt::CaseInsensitive);
}
bool UBSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
UBDocumentTreeModel *model = dynamic_cast<UBDocumentTreeModel*>(sourceModel());
if(model){
//if it's a top level folder
//in other words : myDocuments, models and trash folder
if(model->isToplevel(left) || model->isToplevel(right))
{
return false;
}
}
return QSortFilterProxyModel::lessThan(left, right);
}

@ -0,0 +1,15 @@
#ifndef UBSORTFILTERPROXYMODEL_H
#define UBSORTFILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
#include "core/UBPersistenceManager.h"
class UBSortFilterProxyModel : public QSortFilterProxyModel
{
public:
UBSortFilterProxyModel();
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
};
#endif // UBSORTFILTERPROXYMODEL_H

@ -1,6 +1,11 @@
HEADERS += src/document/UBDocumentController.h \
HEADERS += \
src/document/UBDocumentContainer.h \
src/document/UBDocumentProxy.h
SOURCES += src/document/UBDocumentController.cpp \
src/document/UBDocumentController.h \
src/document/UBDocumentProxy.h \
src/document/UBSortFilterProxyModel.h
SOURCES += \
src/document/UBDocumentContainer.cpp \
src/document/UBDocumentProxy.cpp
src/document/UBDocumentController.cpp \
src/document/UBDocumentProxy.cpp \
src/document/UBSortFilterProxyModel.cpp

@ -11,7 +11,7 @@ HEADERS += src/gui/UBThumbnailView.h \
src/gui/UBResources.h \
src/gui/UBMessageWindow.h \
src/gui/UBDocumentThumbnailWidget.h \
src/gui/UBDocumentTreeWidget.h \
# src/gui/UBDocumentTreeWidget.h \
src/gui/UBMousePressFilter.h \
src/gui/UBBlackoutWidget.h \
src/gui/UBMainWindow.h \
@ -56,7 +56,7 @@ SOURCES += src/gui/UBThumbnailView.cpp \
src/gui/UBResources.cpp \
src/gui/UBMessageWindow.cpp \
src/gui/UBDocumentThumbnailWidget.cpp \
src/gui/UBDocumentTreeWidget.cpp \
# src/gui/UBDocumentTreeWidget.cpp \
src/gui/UBMousePressFilter.cpp \
src/gui/UBBlackoutWidget.cpp \
src/gui/UBMainWindow.cpp \

Loading…
Cancel
Save