/*
* 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 <QtNetwork>
# include <QtXml>
# include "UBGraphicsWidgetItem.h"
# include "UBGraphicsScene.h"
# include "UBGraphicsItemDelegate.h"
# include "UBGraphicsWidgetItemDelegate.h"
# include "UBGraphicsDelegateFrame.h"
# include "api/UBWidgetUniboardAPI.h"
# include "api/UBW3CWidgetAPI.h"
# include "board/UBBoardController.h"
# include "core/memcheck.h"
# include "core/UBApplicationController.h"
# include "core/UBApplication.h"
# include "core/UBSettings.h"
# include "frameworks/UBFileSystemUtils.h"
# include "frameworks/UBPlatformUtils.h"
# include "network/UBNetworkAccessManager.h"
# include "web/UBWebPage.h"
# include "web/UBWebKitUtils.h"
# include "web/UBWebController.h"
bool UBGraphicsWidgetItem : : sInlineJavaScriptLoaded = false ;
QStringList UBGraphicsWidgetItem : : sInlineJavaScripts ;
UBGraphicsWidgetItem : : UBGraphicsWidgetItem ( const QUrl & pWidgetUrl , QGraphicsItem * parent )
: QGraphicsWebView ( parent )
, mInitialLoadDone ( false )
, mIsFreezable ( true )
, mIsResizable ( false )
, mLoadIsErronous ( false )
, mCanBeContent ( 0 )
, mCanBeTool ( 0 )
, mWidgetUrl ( pWidgetUrl )
, mIsFrozen ( false )
, mIsTakingSnapshot ( false )
, mShouldMoveWidget ( false )
, mUniboardAPI ( 0 )
{
setData ( UBGraphicsItemData : : ItemLayerType , QVariant ( itemLayerType : : ObjectItem ) ) ; //Necessary to set if we want z value to be assigned correctly
QGraphicsWebView : : setPage ( new UBWebPage ( this ) ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : JavaEnabled , true ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : PluginsEnabled , true ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : LocalStorageDatabaseEnabled , true ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : OfflineWebApplicationCacheEnabled , true ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : OfflineStorageDatabaseEnabled , true ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : JavascriptCanAccessClipboard , true ) ;
QGraphicsWebView : : settings ( ) - > setAttribute ( QWebSettings : : DnsPrefetchEnabled , true ) ;
page ( ) - > setNetworkAccessManager ( UBNetworkAccessManager : : defaultAccessManager ( ) ) ;
setAcceptDrops ( true ) ;
setAutoFillBackground ( false ) ;
QPalette pagePalette = page ( ) - > palette ( ) ;
pagePalette . setBrush ( QPalette : : Base , QBrush ( Qt : : transparent ) ) ;
pagePalette . setBrush ( QPalette : : Window , QBrush ( Qt : : transparent ) ) ;
page ( ) - > setPalette ( pagePalette ) ;
QPalette viewPalette = palette ( ) ;
pagePalette . setBrush ( QPalette : : Base , QBrush ( Qt : : transparent ) ) ;
viewPalette . setBrush ( QPalette : : Window , QBrush ( Qt : : transparent ) ) ;
setPalette ( viewPalette ) ;
setDelegate ( new UBGraphicsWidgetItemDelegate ( this ) ) ;
setFlag ( QGraphicsItem : : ItemSendsGeometryChanges , true ) ;
QGraphicsWebView : : setAcceptHoverEvents ( true ) ;
}
UBGraphicsWidgetItem : : ~ UBGraphicsWidgetItem ( )
{
/* NOOP */
}
void UBGraphicsWidgetItem : : initialize ( )
{
setMinimumSize ( nominalSize ( ) ) ;
setData ( UBGraphicsItemData : : itemLayerType , QVariant ( itemLayerType : : ObjectItem ) ) ; // Necessary to set if we want z value to be assigned correctly
if ( Delegate ( ) & & Delegate ( ) - > frame ( ) & & resizable ( ) )
Delegate ( ) - > frame ( ) - > setOperationMode ( UBGraphicsDelegateFrame : : Resizing ) ;
QPalette palette = page ( ) - > palette ( ) ;
palette . setBrush ( QPalette : : Base , QBrush ( Qt : : transparent ) ) ;
page ( ) - > setPalette ( palette ) ;
page ( ) - > setLinkDelegationPolicy ( QWebPage : : DelegateAllLinks ) ;
connect ( page ( ) - > mainFrame ( ) , SIGNAL ( javaScriptWindowObjectCleared ( ) ) , this , SLOT ( javaScriptWindowObjectCleared ( ) ) ) ;
connect ( page ( ) , SIGNAL ( geometryChangeRequested ( const QRect & ) ) , this , SLOT ( geometryChangeRequested ( const QRect & ) ) ) ;
connect ( this , SIGNAL ( loadFinished ( bool ) ) , this , SLOT ( mainFrameLoadFinished ( bool ) ) ) ;
connect ( page ( ) - > mainFrame ( ) , SIGNAL ( initialLayoutCompleted ( ) ) , this , SLOT ( initialLayoutCompleted ( ) ) ) ;
connect ( page ( ) , SIGNAL ( linkClicked ( const QUrl & ) ) , this , SLOT ( onLinkClicked ( const QUrl & ) ) ) ;
}
void UBGraphicsWidgetItem : : onLinkClicked ( const QUrl & url )
{
load ( url ) ;
}
void UBGraphicsWidgetItem : : initialLayoutCompleted ( )
{
mInitialLoadDone = true ;
}
QUrl UBGraphicsWidgetItem : : mainHtml ( )
{
return mMainHtmlUrl ;
}
void UBGraphicsWidgetItem : : loadMainHtml ( )
{
mInitialLoadDone = false ;
load ( mMainHtmlUrl ) ;
}
QUrl UBGraphicsWidgetItem : : widgetUrl ( )
{
return mWidgetUrl ;
}
QString UBGraphicsWidgetItem : : mainHtmlFileName ( )
{
return mMainHtmlFileName ;
}
bool UBGraphicsWidgetItem : : canBeContent ( )
{
// if we under MAC OS
# if defined(Q_OS_MAC)
return mCanBeContent & UBGraphicsWidgetItem : : type_MAC ;
# endif
// if we under UNIX OS
# if defined(Q_OS_UNIX)
return mCanBeContent & UBGraphicsWidgetItem : : type_UNIX ;
# endif
// if we under WINDOWS OS
# if defined(Q_OS_WIN)
return mCanBeContent & UBGraphicsWidgetItem : : type_WIN ;
# endif
}
bool UBGraphicsWidgetItem : : canBeTool ( )
{
// if we under MAC OS
# if defined(Q_OS_MAC)
return mCanBeTool & UBGraphicsWidgetItem : : type_MAC ;
# endif
// if we under UNIX OS
# if defined(Q_OS_UNIX)
return mCanBeTool & UBGraphicsWidgetItem : : type_UNIX ;
# endif
// if we under WINDOWS OS
# if defined(Q_OS_WIN)
return mCanBeTool & UBGraphicsWidgetItem : : type_WIN ;
# endif
}
QString UBGraphicsWidgetItem : : preference ( const QString & key ) const
{
return mPreferences . value ( key ) ;
}
void UBGraphicsWidgetItem : : setPreference ( const QString & key , QString value )
{
if ( key = = " " | | ( mPreferences . contains ( key ) & & mPreferences . value ( key ) = = value ) )
return ;
mPreferences . insert ( key , value ) ;
if ( scene ( ) )
scene ( ) - > setModified ( true ) ;
}
QMap < QString , QString > UBGraphicsWidgetItem : : preferences ( ) const
{
return mPreferences ;
}
void UBGraphicsWidgetItem : : removePreference ( const QString & key )
{
mPreferences . remove ( key ) ;
}
void UBGraphicsWidgetItem : : removeAllPreferences ( )
{
mPreferences . clear ( ) ;
}
QString UBGraphicsWidgetItem : : datastoreEntry ( const QString & key ) const
{
if ( mDatastore . contains ( key ) )
return mDatastore . value ( key ) ;
else
return QString ( ) ;
}
void UBGraphicsWidgetItem : : setDatastoreEntry ( const QString & key , QString value )
{
if ( key = = " " | | ( mDatastore . contains ( key ) & & mDatastore . value ( key ) = = value ) )
return ;
mDatastore . insert ( key , value ) ;
if ( scene ( ) )
scene ( ) - > setModified ( true ) ;
}
QMap < QString , QString > UBGraphicsWidgetItem : : datastoreEntries ( ) const
{
return mDatastore ;
}
void UBGraphicsWidgetItem : : removeDatastoreEntry ( const QString & key )
{
mDatastore . remove ( key ) ;
}
void UBGraphicsWidgetItem : : removeAllDatastoreEntries ( )
{
mDatastore . clear ( ) ;
}
void UBGraphicsWidgetItem : : removeScript ( )
{
if ( page ( ) & & page ( ) - > mainFrame ( ) )
page ( ) - > mainFrame ( ) - > evaluateJavaScript ( " if(widget && widget.onremove) { widget.onremove();} " ) ;
}
void UBGraphicsWidgetItem : : processDropEvent ( QGraphicsSceneDragDropEvent * event )
{
mUniboardAPI - > ProcessDropEvent ( event ) ;
}
bool UBGraphicsWidgetItem : : isDropableData ( const QMimeData * data ) const
{
return mUniboardAPI - > isDropableData ( data ) ;
}
QUrl UBGraphicsWidgetItem : : getOwnFolder ( ) const
{
return ownFolder ;
}
void UBGraphicsWidgetItem : : setOwnFolder ( const QUrl & newFolder )
{
ownFolder = newFolder ;
}
void UBGraphicsWidgetItem : : setSnapshotPath ( const QUrl & newFilePath )
{
SnapshotFile = newFilePath ;
}
QUrl UBGraphicsWidgetItem : : getSnapshotPath ( )
{
return SnapshotFile ;
}
void UBGraphicsWidgetItem : : clearSource ( )
{
UBFileSystemUtils : : deleteDir ( getOwnFolder ( ) . toLocalFile ( ) ) ;
UBFileSystemUtils : : deleteFile ( getSnapshotPath ( ) . toLocalFile ( ) ) ;
}
void UBGraphicsWidgetItem : : setUuid ( const QUuid & pUuid )
{
UBItem : : setUuid ( pUuid ) ;
setData ( UBGraphicsItemData : : ItemUuid , QVariant ( pUuid ) ) ; //store item uuid inside the QGraphicsItem to fast operations with Items on the scene
}
QSize UBGraphicsWidgetItem : : nominalSize ( ) const
{
return mNominalSize ;
}
bool UBGraphicsWidgetItem : : hasLoadedSuccessfully ( ) const
{
return ( mInitialLoadDone & & ! mLoadIsErronous ) ;
}
bool UBGraphicsWidgetItem : : freezable ( )
{
return mIsFreezable ;
}
bool UBGraphicsWidgetItem : : resizable ( )
{
return mIsResizable ;
}
bool UBGraphicsWidgetItem : : isFrozen ( )
{
return mIsFrozen ;
}
QPixmap UBGraphicsWidgetItem : : snapshot ( )
{
return mSnapshot ;
}
QPixmap UBGraphicsWidgetItem : : takeSnapshot ( )
{
mIsTakingSnapshot = true ;
QPixmap pixmap ( size ( ) . toSize ( ) ) ;
pixmap . fill ( Qt : : transparent ) ;
QPainter painter ( & pixmap ) ;
QStyleOptionGraphicsItem options ;
paint ( & painter , & options ) ;
mIsTakingSnapshot = false ;
mSnapshot = pixmap ;
return pixmap ;
}
void UBGraphicsWidgetItem : : setSnapshot ( const QPixmap & pix )
{
mSnapshot = pix ;
}
UBGraphicsScene * UBGraphicsWidgetItem : : scene ( )
{
return qobject_cast < UBGraphicsScene * > ( QGraphicsItem : : scene ( ) ) ;
}
int UBGraphicsWidgetItem : : widgetType ( const QUrl & pUrl )
{
QString mime = UBFileSystemUtils : : mimeTypeFromFileName ( pUrl . toString ( ) ) ;
if ( mime = = " application/vnd.apple-widget " )
return UBWidgetType : : Apple ;
else if ( mime = = " application/widget " )
return UBWidgetType : : W3C ;
else
return UBWidgetType : : Other ;
}
QString UBGraphicsWidgetItem : : widgetName ( const QUrl & widgetPath )
{
QString name ;
QString version ;
QFile w3CConfigFile ( widgetPath . toLocalFile ( ) + " /config.xml " ) ;
QFile appleConfigFile ( widgetPath . toLocalFile ( ) + " /Info.plist " ) ;
if ( w3CConfigFile . exists ( ) & & w3CConfigFile . open ( QFile : : ReadOnly ) ) {
QDomDocument doc ;
doc . setContent ( w3CConfigFile . readAll ( ) ) ;
QDomElement root = doc . firstChildElement ( " widget " ) ;
if ( ! root . isNull ( ) ) {
QDomElement nameElement = root . firstChildElement ( " name " ) ;
if ( ! nameElement . isNull ( ) )
name = nameElement . text ( ) ;
version = root . attribute ( " version " , " " ) ;
}
w3CConfigFile . close ( ) ;
}
else if ( appleConfigFile . exists ( ) & & appleConfigFile . open ( QFile : : ReadOnly ) ) {
QDomDocument doc ;
doc . setContent ( appleConfigFile . readAll ( ) ) ;
QDomElement root = doc . firstChildElement ( " plist " ) ;
if ( ! root . isNull ( ) ) {
QDomElement dictElement = root . firstChildElement ( " dict " ) ;
if ( ! dictElement . isNull ( ) ) {
QDomNodeList childNodes = dictElement . childNodes ( ) ;
/* looking for something like
* . .
* < key > CFBundleDisplayName < / key >
* < string > brain scans < / string >
* . .
*/
for ( int i = 0 ; i < childNodes . count ( ) - 1 ; i + + ) {
if ( childNodes . at ( i ) . isElement ( ) ) {
QDomElement elKey = childNodes . at ( i ) . toElement ( ) ;
if ( elKey . text ( ) = = " CFBundleDisplayName " ) {
if ( childNodes . at ( i + 1 ) . isElement ( ) ) {
QDomElement elValue = childNodes . at ( i + 1 ) . toElement ( ) ;
name = elValue . text ( ) ;
}
}
else if ( elKey . text ( ) = = " CFBundleShortVersionString " ) {
if ( childNodes . at ( i + 1 ) . isElement ( ) ) {
QDomElement elValue = childNodes . at ( i + 1 ) . toElement ( ) ;
version = elValue . text ( ) ;
}
}
}
}
}
}
appleConfigFile . close ( ) ;
}
QString result ;
if ( name . length ( ) > 0 ) {
result = name ;
if ( version . length ( ) > 0 ) {
result + = " " ;
result + = version ;
}
}
return result ;
}
QString UBGraphicsWidgetItem : : iconFilePath ( const QUrl & pUrl )
{
/* TODO UB 4.x read config.xml widget.icon param first */
QStringList files ;
files < < " icon.svg " ; /* W3C widget default 1 */
files < < " icon.ico " ; /* W3C widget default 2 */
files < < " icon.png " ; /* W3C widget default 3 */
files < < " icon.gif " ; /* W3C widget default 4 */
files < < " Icon.png " ; /* Apple widget default */
QString file = UBFileSystemUtils : : getFirstExistingFileFromList ( pUrl . toLocalFile ( ) , files ) ;
/* default */
if ( file . length ( ) = = 0 )
{
file = QString ( " :/images/defaultWidgetIcon.png " ) ;
}
return file ;
}
void UBGraphicsWidgetItem : : freeze ( )
{
QPixmap pix = takeSnapshot ( ) ;
mIsFrozen = true ;
setSnapshot ( pix ) ;
}
void UBGraphicsWidgetItem : : unFreeze ( )
{
mIsFrozen = false ;
}
bool UBGraphicsWidgetItem : : event ( QEvent * event )
{
if ( mShouldMoveWidget & & event - > type ( ) = = QEvent : : MouseMove ) {
QMouseEvent * mouseMoveEvent = static_cast < QMouseEvent * > ( event ) ;
if ( mouseMoveEvent - > buttons ( ) & Qt : : LeftButton ) {
QPointF scenePos = mapToScene ( mouseMoveEvent - > pos ( ) ) ;
QPointF newPos = pos ( ) + scenePos - mLastMousePos ;
setPos ( newPos ) ;
mLastMousePos = scenePos ;
event - > accept ( ) ;
return true ;
}
}
else if ( event - > type ( ) = = QEvent : : ShortcutOverride )
event - > accept ( ) ;
return QGraphicsWebView : : event ( event ) ;
}
void UBGraphicsWidgetItem : : dropEvent ( QGraphicsSceneDragDropEvent * event )
{
processDropEvent ( event ) ;
QGraphicsWebView : : dropEvent ( event ) ;
}
void UBGraphicsWidgetItem : : mousePressEvent ( QGraphicsSceneMouseEvent * event )
{
if ( ! Delegate ( ) - > mousePressEvent ( event ) )
setSelected ( true ) ; /* forcing selection */
QGraphicsWebView : : mousePressEvent ( event ) ;
// did webkit consume the mouse press ?
mShouldMoveWidget = ! event - > isAccepted ( ) & & ( event - > buttons ( ) & Qt : : LeftButton ) ;
mLastMousePos = mapToScene ( event - > pos ( ) ) ;
event - > accept ( ) ;
}
void UBGraphicsWidgetItem : : mouseReleaseEvent ( QGraphicsSceneMouseEvent * event )
{
mShouldMoveWidget = false ;
Delegate ( ) - > mouseReleaseEvent ( event ) ;
QGraphicsWebView : : mouseReleaseEvent ( event ) ;
}
void UBGraphicsWidgetItem : : hoverEnterEvent ( QGraphicsSceneHoverEvent * event )
{
sendJSEnterEvent ( ) ;
Delegate ( ) - > hoverEnterEvent ( event ) ;
}
void UBGraphicsWidgetItem : : hoverLeaveEvent ( QGraphicsSceneHoverEvent * event )
{
sendJSLeaveEvent ( ) ;
Delegate ( ) - > hoverLeaveEvent ( event ) ;
}
void UBGraphicsWidgetItem : : sendJSEnterEvent ( )
{
if ( page ( ) & & page ( ) - > mainFrame ( ) )
page ( ) - > mainFrame ( ) - > evaluateJavaScript ( " if(widget && widget.onenter) { widget.onenter();} " ) ;
}
void UBGraphicsWidgetItem : : sendJSLeaveEvent ( )
{
if ( page ( ) & & page ( ) - > mainFrame ( ) )
page ( ) - > mainFrame ( ) - > evaluateJavaScript ( " if(widget && widget.onleave) { widget.onleave();} " ) ;
}
void UBGraphicsWidgetItem : : injectInlineJavaScript ( )
{
if ( ! sInlineJavaScriptLoaded ) {
sInlineJavaScripts = UBApplication : : applicationController - > widgetInlineJavaScripts ( ) ;
sInlineJavaScriptLoaded = true ;
}
foreach ( QString script , sInlineJavaScripts )
page ( ) - > mainFrame ( ) - > evaluateJavaScript ( script ) ;
}
void UBGraphicsWidgetItem : : paint ( QPainter * painter , const QStyleOptionGraphicsItem * option , QWidget * widget )
{
if ( scene ( ) & & scene ( ) - > renderingContext ( ) ! = UBGraphicsScene : : Screen ) {
painter - > drawPixmap ( 0 , 0 , snapshot ( ) ) ;
}
else {
QGraphicsWebView : : paint ( painter , option , widget ) ;
}
if ( ! mInitialLoadDone ) {
QString message ;
message = tr ( " Loading ... " ) ;
painter - > setFont ( QFont ( " Arial " , 12 ) ) ;
QFontMetrics fm = painter - > fontMetrics ( ) ;
QRect txtBoundingRect = fm . boundingRect ( message ) ;
txtBoundingRect . moveCenter ( rect ( ) . center ( ) . toPoint ( ) ) ;
txtBoundingRect . adjust ( - 10 , - 5 , 10 , 5 ) ;
painter - > setPen ( Qt : : NoPen ) ;
painter - > setBrush ( UBSettings : : paletteColor ) ;
painter - > drawRoundedRect ( txtBoundingRect , 3 , 3 ) ;
painter - > setPen ( Qt : : white ) ;
painter - > drawText ( rect ( ) , Qt : : AlignCenter , message ) ;
}
Delegate ( ) - > postpaint ( painter , option , widget ) ;
}
void UBGraphicsWidgetItem : : geometryChangeRequested ( const QRect & geom )
{
resize ( geom . width ( ) , geom . height ( ) ) ;
}
void UBGraphicsWidgetItem : : javaScriptWindowObjectCleared ( )
{
injectInlineJavaScript ( ) ;
if ( ! mUniboardAPI )
mUniboardAPI = new UBWidgetUniboardAPI ( scene ( ) , this ) ;
page ( ) - > mainFrame ( ) - > addToJavaScriptWindowObject ( " sankore " , mUniboardAPI ) ;
}
void UBGraphicsWidgetItem : : mainFrameLoadFinished ( bool ok )
{
mLoadIsErronous = ! ok ;
update ( boundingRect ( ) ) ;
if ( mInitialLoadDone & & scene ( ) & & scene ( ) - > renderingContext ( ) = = UBGraphicsScene : : Screen )
takeSnapshot ( ) ;
}
void UBGraphicsWidgetItem : : wheelEvent ( QGraphicsSceneWheelEvent * event )
{
if ( Delegate ( ) - > wheelEvent ( event ) )
{
QGraphicsWebView : : wheelEvent ( event ) ;
event - > accept ( ) ;
}
}
QVariant UBGraphicsWidgetItem : : itemChange ( GraphicsItemChange change , const QVariant & value )
{
if ( ( change = = QGraphicsItem : : ItemSelectedHasChanged ) & & scene ( ) ) {
if ( isSelected ( ) )
scene ( ) - > setActiveWindow ( this ) ;
else
if ( scene ( ) - > activeWindow ( ) = = this )
scene ( ) - > setActiveWindow ( 0 ) ;
}
QVariant newValue = Delegate ( ) - > itemChange ( change , value ) ;
return QGraphicsWebView : : itemChange ( change , newValue ) ;
}
void UBGraphicsWidgetItem : : resize ( qreal w , qreal h )
{
UBGraphicsWidgetItem : : resize ( QSizeF ( w , h ) ) ;
}
void UBGraphicsWidgetItem : : resize ( const QSizeF & pSize )
{
if ( pSize ! = size ( ) ) {
QGraphicsWebView : : setMaximumSize ( pSize . width ( ) , pSize . height ( ) ) ;
QGraphicsWebView : : resize ( pSize . width ( ) , pSize . height ( ) ) ;
if ( Delegate ( ) )
Delegate ( ) - > positionHandles ( ) ;
if ( scene ( ) )
scene ( ) - > setModified ( true ) ;
}
}
QSizeF UBGraphicsWidgetItem : : size ( ) const
{
return QGraphicsWebView : : size ( ) ;
}
UBGraphicsAppleWidgetItem : : UBGraphicsAppleWidgetItem ( const QUrl & pWidgetUrl , QGraphicsItem * parent )
: UBGraphicsWidgetItem ( pWidgetUrl , parent )
{
QString path = pWidgetUrl . toLocalFile ( ) ;
if ( ! path . endsWith ( " .wdgt " ) & & ! path . endsWith ( " .wdgt/ " ) ) {
int lastSlashIndex = path . lastIndexOf ( " / " ) ;
if ( lastSlashIndex > 0 )
path = path . mid ( 0 , lastSlashIndex + 1 ) ;
}
QFile plistFile ( path + " /Info.plist " ) ;
plistFile . open ( QFile : : ReadOnly ) ;
QByteArray plistBin = plistFile . readAll ( ) ;
QString plist = QString : : fromUtf8 ( plistBin ) ;
int mainHtmlIndex = plist . indexOf ( " MainHTML " ) ;
int mainHtmlIndexStart = plist . indexOf ( " <string> " , mainHtmlIndex ) ;
int mainHtmlIndexEnd = plist . indexOf ( " </string> " , mainHtmlIndexStart ) ;
if ( mainHtmlIndex > - 1 & & mainHtmlIndexStart > - 1 & & mainHtmlIndexEnd > - 1 )
mMainHtmlFileName = plist . mid ( mainHtmlIndexStart + 8 , mainHtmlIndexEnd - mainHtmlIndexStart - 8 ) ;
mMainHtmlUrl = pWidgetUrl ;
mMainHtmlUrl . setPath ( pWidgetUrl . path ( ) + " / " + mMainHtmlFileName ) ;
load ( mMainHtmlUrl ) ;
QPixmap defaultPixmap ( pWidgetUrl . toLocalFile ( ) + " /Default.png " ) ;
setMaximumSize ( defaultPixmap . size ( ) ) ;
mNominalSize = defaultPixmap . size ( ) ;
initialize ( ) ;
}
UBGraphicsAppleWidgetItem : : ~ UBGraphicsAppleWidgetItem ( )
{
/* NOOP */
}
void UBGraphicsAppleWidgetItem : : setUuid ( const QUuid & pUuid )
{
UBItem : : setUuid ( pUuid ) ;
setData ( UBGraphicsItemData : : ItemUuid , QVariant ( pUuid ) ) ; //store item uuid inside the QGraphicsItem to fast operations with Items on the scene
}
UBItem * UBGraphicsAppleWidgetItem : : deepCopy ( ) const
{
UBGraphicsAppleWidgetItem * appleWidget = new UBGraphicsAppleWidgetItem ( QGraphicsWebView : : url ( ) , parentItem ( ) ) ;
copyItemParameters ( appleWidget ) ;
return appleWidget ;
}
void UBGraphicsAppleWidgetItem : : copyItemParameters ( UBItem * copy ) const
{
UBGraphicsAppleWidgetItem * cp = dynamic_cast < UBGraphicsAppleWidgetItem * > ( copy ) ;
if ( cp )
{
foreach ( QString key , mPreferences . keys ( ) )
{
cp - > setPreference ( key , mPreferences . value ( key ) ) ;
}
foreach ( QString key , mDatastore . keys ( ) )
{
cp - > setDatastoreEntry ( key , mDatastore . value ( key ) ) ;
}
cp - > setSourceUrl ( this - > sourceUrl ( ) ) ;
}
}
bool UBGraphicsW3CWidgetItem : : sTemplateLoaded = false ;
QString UBGraphicsW3CWidgetItem : : sNPAPIWrappperConfigTemplate ;
QMap < QString , QString > UBGraphicsW3CWidgetItem : : sNPAPIWrapperTemplates ;
UBGraphicsW3CWidgetItem : : UBGraphicsW3CWidgetItem ( const QUrl & pWidgetUrl , QGraphicsItem * parent )
: UBGraphicsWidgetItem ( pWidgetUrl , parent )
, mW3CWidgetAPI ( 0 )
{
QString path = pWidgetUrl . toLocalFile ( ) ;
QDir potentialDir ( path ) ;
if ( ! path . endsWith ( " .wgt " ) & & ! path . endsWith ( " .wgt/ " ) & & ! potentialDir . exists ( ) ) {
int lastSlashIndex = path . lastIndexOf ( " / " ) ;
if ( lastSlashIndex > 0 )
path = path . mid ( 0 , lastSlashIndex + 1 ) ;
}
if ( ! path . endsWith ( " / " ) )
path + = " / " ;
int width = 300 ;
int height = 150 ;
QFile configFile ( path + " config.xml " ) ;
configFile . open ( QFile : : ReadOnly ) ;
QDomDocument doc ;
doc . setContent ( configFile . readAll ( ) ) ;
QDomNodeList widgetDomList = doc . elementsByTagName ( " widget " ) ;
if ( widgetDomList . count ( ) > 0 ) {
QDomElement widgetElement = widgetDomList . item ( 0 ) . toElement ( ) ;
width = widgetElement . attribute ( " width " , " 300 " ) . toInt ( ) ;
height = widgetElement . attribute ( " height " , " 150 " ) . toInt ( ) ;
mMetadatas . id = widgetElement . attribute ( " id " , " " ) ;
/* some early widget (<= 4.3.4) where using identifier instead of id */
if ( mMetadatas . id . length ( ) = = 0 )
mMetadatas . id = widgetElement . attribute ( " identifier " , " " ) ;
mMetadatas . version = widgetElement . attribute ( " version " , " " ) ;
/* TODO UB 4.x map properly ub namespace */
mIsResizable = widgetElement . attribute ( " ub:resizable " , " false " ) = = " true " ;
mIsFreezable = widgetElement . attribute ( " ub:freezable " , " true " ) = = " true " ;
QString roles = widgetElement . attribute ( " ub:roles " , " content tool " ) . trimmed ( ) . toLower ( ) ;
/* ------------------------------ */
if ( roles = = " " | | roles . contains ( " tool " ) )
mCanBeTool = UBGraphicsWidgetItem : : type_ALL ;
if ( roles . contains ( " twin " ) )
mCanBeTool | = UBGraphicsWidgetItem : : type_WIN ;
if ( roles . contains ( " tmac " ) )
mCanBeTool | = UBGraphicsWidgetItem : : type_MAC ;
if ( roles . contains ( " tunix " ) )
mCanBeTool | = UBGraphicsWidgetItem : : type_UNIX ;
/* --------- */
if ( roles = = " " | | roles . contains ( " content " ) )
mCanBeContent = UBGraphicsWidgetItem : : type_ALL ;
if ( roles . contains ( " cwin " ) )
mCanBeContent | = UBGraphicsWidgetItem : : type_WIN ;
if ( roles . contains ( " cmac " ) )
mCanBeContent | = UBGraphicsWidgetItem : : type_MAC ;
if ( roles . contains ( " cunix " ) )
mCanBeContent | = UBGraphicsWidgetItem : : type_UNIX ;
//------------------------------//
QDomNodeList contentDomList = widgetElement . elementsByTagName ( " content " ) ;
if ( contentDomList . count ( ) > 0 ) {
QDomElement contentElement = contentDomList . item ( 0 ) . toElement ( ) ;
mMainHtmlFileName = contentElement . attribute ( " src " , " " ) ;
}
mMetadatas . name = textForSubElementByLocale ( widgetElement , " name " , QLocale : : system ( ) ) ;
mMetadatas . description = textForSubElementByLocale ( widgetElement , " description " , QLocale : : system ( ) ) ;
QDomNodeList authorDomList = widgetElement . elementsByTagName ( " author " ) ;
if ( authorDomList . count ( ) > 0 ) {
QDomElement authorElement = authorDomList . item ( 0 ) . toElement ( ) ;
mMetadatas . author = authorElement . text ( ) ;
mMetadatas . authorHref = authorElement . attribute ( " href " , " " ) ;
mMetadatas . authorEmail = authorElement . attribute ( " email " , " " ) ;
}
QDomNodeList propertiesDomList = widgetElement . elementsByTagName ( " preference " ) ;
for ( uint i = 0 ; i < propertiesDomList . length ( ) ; i + + ) {
QDomElement preferenceElement = propertiesDomList . at ( i ) . toElement ( ) ;
QString prefName = preferenceElement . attribute ( " name " , " " ) ;
if ( prefName . length ( ) > 0 ) {
QString prefValue = preferenceElement . attribute ( " value " , " " ) ;
bool readOnly = ( preferenceElement . attribute ( " readonly " , " false " ) = = " true " ) ;
mPreferences . insert ( prefName , PreferenceValue ( prefValue , readOnly ) ) ;
}
}
}
if ( mMainHtmlFileName . length ( ) = = 0 ) {
QFile defaultStartFile ( path + " index.htm " ) ;
if ( defaultStartFile . exists ( ) )
mMainHtmlFileName = " index.htm " ;
else {
QFile secondDefaultStartFile ( path + " index.html " ) ;
if ( secondDefaultStartFile . exists ( ) )
mMainHtmlFileName = " index.html " ;
}
}
mMainHtmlUrl = pWidgetUrl ;
mMainHtmlUrl . setPath ( pWidgetUrl . path ( ) + " / " + mMainHtmlFileName ) ;
/* is it a valid local file ? */
QFile f ( mMainHtmlUrl . toLocalFile ( ) ) ;
if ( ! f . exists ( ) )
mMainHtmlUrl = QUrl ( mMainHtmlFileName ) ;
connect ( page ( ) - > mainFrame ( ) , SIGNAL ( javaScriptWindowObjectCleared ( ) ) , this , SLOT ( javaScriptWindowObjectCleared ( ) ) ) ;
connect ( UBApplication : : boardController , SIGNAL ( activeSceneChanged ( ) ) , this , SLOT ( javaScriptWindowObjectCleared ( ) ) ) ;
load ( mMainHtmlUrl ) ;
setMaximumSize ( QSize ( width , height ) ) ;
mNominalSize = QSize ( width , height ) ;
initialize ( ) ;
setOwnFolder ( pWidgetUrl ) ;
}
UBGraphicsW3CWidgetItem : : ~ UBGraphicsW3CWidgetItem ( )
{
/* NOOP */
}
void UBGraphicsW3CWidgetItem : : setUuid ( const QUuid & pUuid )
{
UBItem : : setUuid ( pUuid ) ;
setData ( UBGraphicsItemData : : ItemUuid , QVariant ( pUuid ) ) ; //store item uuid inside the QGraphicsItem to fast operations with Items on the scene
}
UBItem * UBGraphicsW3CWidgetItem : : deepCopy ( ) const
{
UBGraphicsW3CWidgetItem * copy = new UBGraphicsW3CWidgetItem ( mWidgetUrl , parentItem ( ) ) ;
copy - > setUuid ( this - > uuid ( ) ) ; // this is OK for now as long as Widgets are imutable
copyItemParameters ( copy ) ;
return copy ;
}
QMap < QString , UBGraphicsW3CWidgetItem : : PreferenceValue > UBGraphicsW3CWidgetItem : : preferences ( )
{
return mPreferences ;
}
UBGraphicsW3CWidgetItem : : Metadata UBGraphicsW3CWidgetItem : : metadatas ( ) const
{
return mMetadatas ;
}
QString UBGraphicsW3CWidgetItem : : createNPAPIWrapper ( const QString & url , const QString & pMimeType , const QSize & sizeHint , const QString & pName )
{
const QString userWidgetPath = UBSettings : : settings ( ) - > userInteractiveDirectory ( ) + " / " + tr ( " Web " ) ;
QDir userWidgetDir ( userWidgetPath ) ;
return createNPAPIWrapperInDir ( url , userWidgetDir , pMimeType , sizeHint , pName ) ;
}
QString UBGraphicsW3CWidgetItem : : createNPAPIWrapperInDir ( const QString & pUrl , const QDir & pDir , const QString & pMimeType , const QSize & sizeHint , const QString & pName )
{
QString url = pUrl ;
url = UBFileSystemUtils : : removeLocalFilePrefix ( url ) ;
QString name = pName ;
QFileInfo fi ( url ) ;
if ( name . length ( ) = = 0 )
name = fi . baseName ( ) ;
if ( fi . exists ( ) )
url = fi . fileName ( ) ;
loadNPAPIWrappersTemplates ( ) ;
QString htmlTemplate ;
if ( pMimeType . length ( ) > 0 & & sNPAPIWrapperTemplates . contains ( pMimeType ) )
htmlTemplate = sNPAPIWrapperTemplates . value ( pMimeType ) ;
else {
QString extension = UBFileSystemUtils : : extension ( url ) ;
if ( sNPAPIWrapperTemplates . contains ( extension ) )
htmlTemplate = sNPAPIWrapperTemplates . value ( extension ) ;
}
if ( htmlTemplate . length ( ) > 0 ) {
htmlTemplate = htmlTemplate . replace ( QString ( " {in.url} " ) , url )
. replace ( QString ( " {in.width} " ) , QString ( " %1 " ) . arg ( sizeHint . width ( ) ) )
. replace ( QString ( " {in.height} " ) , QString ( " %1 " ) . arg ( sizeHint . height ( ) ) ) ;
QString configTemplate = sNPAPIWrappperConfigTemplate
. replace ( QString ( " {in.id} " ) , url )
. replace ( QString ( " {in.width} " ) , QString ( " %1 " ) . arg ( sizeHint . width ( ) ) )
. replace ( QString ( " {in.height} " ) , QString ( " %1 " ) . arg ( sizeHint . height ( ) ) )
. replace ( QString ( " {in.name} " ) , name )
. replace ( QString ( " {in.startFile} " ) , QString ( " index.htm " ) ) ;
QString dirPath = pDir . path ( ) ;
if ( ! pDir . exists ( ) )
pDir . mkpath ( dirPath ) ;
QString widgetLibraryPath = dirPath + " / " + name + " .wgt " ;
QDir widgetLibraryDir ( widgetLibraryPath ) ;
if ( widgetLibraryDir . exists ( ) )
if ( ! UBFileSystemUtils : : deleteDir ( widgetLibraryDir . path ( ) ) )
qWarning ( ) < < " Cannot delete old widget " < < widgetLibraryDir . path ( ) ;
widgetLibraryDir . mkpath ( widgetLibraryPath ) ;
if ( fi . exists ( ) ) {
QString target = widgetLibraryPath + " / " + fi . fileName ( ) ;
QString source = pUrl ;
source = UBFileSystemUtils : : removeLocalFilePrefix ( source ) ;
QFile : : copy ( source , target ) ;
}
QFile configFile ( widgetLibraryPath + " /config.xml " ) ;
if ( ! configFile . open ( QIODevice : : WriteOnly ) ) {
qWarning ( ) < < " Cannot open file " < < configFile . fileName ( ) ;
return QString ( ) ;
}
QTextStream outConfig ( & configFile ) ;
outConfig . setCodec ( " UTF-8 " ) ;
outConfig < < configTemplate ;
configFile . close ( ) ;
QFile indexFile ( widgetLibraryPath + " /index.htm " ) ;
if ( ! indexFile . open ( QIODevice : : WriteOnly ) ) {
qWarning ( ) < < " Cannot open file " < < indexFile . fileName ( ) ;
return QString ( ) ;
}
QTextStream outIndex ( & indexFile ) ;
outIndex . setCodec ( " UTF-8 " ) ;
outIndex < < htmlTemplate ;
indexFile . close ( ) ;
return widgetLibraryPath ;
}
else
return QString ( ) ;
}
QString UBGraphicsW3CWidgetItem : : createHtmlWrapperInDir ( const QString & html , const QDir & pDir , const QSize & sizeHint , const QString & pName )
{
QString widgetPath = pDir . path ( ) + " / " + pName + " .wgt " ;
widgetPath = UBFileSystemUtils : : nextAvailableFileName ( widgetPath ) ;
QDir widgetDir ( widgetPath ) ;
if ( ! widgetDir . exists ( ) )
widgetDir . mkpath ( widgetDir . path ( ) ) ;
QFile configFile ( widgetPath + " / " + " config.xml " ) ;
if ( configFile . exists ( ) )
configFile . remove ( configFile . fileName ( ) ) ;
if ( ! configFile . open ( QIODevice : : WriteOnly ) ) {
qWarning ( ) < < " Cannot open file " < < configFile . fileName ( ) ;
return " " ;
}
QTextStream outConfig ( & configFile ) ;
outConfig . setCodec ( " UTF-8 " ) ;
outConfig < < " <?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> " < < endl ;
outConfig < < " <widget xmlns= \" http://www.w3.org/ns/widgets \" " < < endl ;
outConfig < < " xmlns:ub= \" http://uniboard.mnemis.com/widgets \" " < < endl ;
outConfig < < " id= \" http://uniboard.mnemis.com/ " < < pName < < " \" " < < endl ;
outConfig < < " version= \" 1.0 \" " < < endl ;
outConfig < < " width= \" " < < sizeHint . width ( ) < < " \" " < < endl ;
outConfig < < " height= \" " < < sizeHint . height ( ) < < " \" " < < endl ;
outConfig < < " ub:resizable= \" true \" > " < < endl ;
outConfig < < " <name> " < < pName < < " </name> " < < endl ;
outConfig < < " <content src= \" " < < pName < < " .html \" /> " < < endl ;
outConfig < < " </widget> " < < endl ;
configFile . close ( ) ;
const QString fullHtmlFileName = widgetPath + " / " + pName + " .html " ;
QFile widgetHtmlFile ( fullHtmlFileName ) ;
if ( widgetHtmlFile . exists ( ) )
widgetHtmlFile . remove ( widgetHtmlFile . fileName ( ) ) ;
if ( ! widgetHtmlFile . open ( QIODevice : : WriteOnly ) ) {
qWarning ( ) < < " cannot open file " < < widgetHtmlFile . fileName ( ) ;
return QString ( ) ;
}
QTextStream outStartFile ( & widgetHtmlFile ) ;
outStartFile . setCodec ( " UTF-8 " ) ;
outStartFile < < " <!DOCTYPE HTML PUBLIC \" -//W3C//DTD HTML 4.01//EN \" \" http://www.w3.org/TR/html4/strict.dtd \" > " < < endl ;
outStartFile < < " <html> " < < endl ;
outStartFile < < " <head> " < < endl ;
outStartFile < < " <meta http-equiv= \" content-type \" content= \" text/html; charset=utf-8 \" > " < < endl ;
outStartFile < < " </head> " < < endl ;
outStartFile < < " <body> " < < endl ;
outStartFile < < html < < endl ;
outStartFile < < " </body> " < < endl ;
outStartFile < < " </html> " < < endl ;
widgetHtmlFile . close ( ) ;
return widgetPath ;
}
QString UBGraphicsW3CWidgetItem : : freezedWidgetPage ( )
{
static QString defaultcontent ;
if ( defaultcontent . isNull ( ) ) {
QString freezedWidgetDefaultContentFilePath = freezedWidgetFilePath ( ) ;
QFile wrapperFile ( freezedWidgetDefaultContentFilePath ) ;
if ( ! wrapperFile . open ( QIODevice : : ReadOnly | QIODevice : : Text ) ) {
qDebug ( ) < < " can't open wrapper file " + freezedWidgetDefaultContentFilePath ;
defaultcontent = " " ;
}
else {
QByteArray arr = wrapperFile . readAll ( ) ;
if ( ! arr . isEmpty ( ) )
defaultcontent = QString ( arr ) ;
else {
qDebug ( ) < < " content of " + freezedWidgetDefaultContentFilePath + " is empty " ;
defaultcontent = QString ( ) ;
}
}
}
return defaultcontent ;
}
QString UBGraphicsW3CWidgetItem : : freezedWidgetFilePath ( )
{
return UBPlatformUtils : : applicationResourcesDirectory ( ) + " /etc/ " + " freezedWidgetWrapper.html " ;
}
bool UBGraphicsW3CWidgetItem : : hasNPAPIWrapper ( const QString & pMimeType )
{
loadNPAPIWrappersTemplates ( ) ;
return sNPAPIWrapperTemplates . contains ( pMimeType ) ;
}
void UBGraphicsW3CWidgetItem : : javaScriptWindowObjectCleared ( )
{
UBGraphicsWidgetItem : : javaScriptWindowObjectCleared ( ) ;
if ( ! mW3CWidgetAPI )
mW3CWidgetAPI = new UBW3CWidgetAPI ( this ) ;
page ( ) - > mainFrame ( ) - > addToJavaScriptWindowObject ( " widget " , mW3CWidgetAPI ) ;
}
void UBGraphicsW3CWidgetItem : : loadNPAPIWrappersTemplates ( )
{
if ( ! sTemplateLoaded ) {
sNPAPIWrapperTemplates . clear ( ) ;
QString etcPath = UBPlatformUtils : : applicationResourcesDirectory ( ) + " /etc/ " ;
QDir etcDir ( etcPath ) ;
foreach ( QString fileName , etcDir . entryList ( ) ) {
if ( fileName . startsWith ( " npapi-wrapper " ) & & ( fileName . endsWith ( " .htm " ) | | fileName . endsWith ( " .html " ) ) ) {
QString htmlContent = UBFileSystemUtils : : readTextFile ( etcPath + fileName ) ;
if ( htmlContent . length ( ) > 0 ) {
QStringList tokens = fileName . split ( " . " ) ;
if ( tokens . length ( ) > = 4 ) {
QString mime = tokens . at ( tokens . length ( ) - 4 ) ;
mime + = " / " + tokens . at ( tokens . length ( ) - 3 ) ;
QString fileExtension = tokens . at ( tokens . length ( ) - 2 ) ;
sNPAPIWrapperTemplates . insert ( mime , htmlContent ) ;
sNPAPIWrapperTemplates . insert ( fileExtension , htmlContent ) ;
}
}
}
}
sNPAPIWrappperConfigTemplate = UBFileSystemUtils : : readTextFile ( etcPath + " npapi-wrapper.config.xml " ) ;
sTemplateLoaded = true ;
}
}
QString UBGraphicsW3CWidgetItem : : textForSubElementByLocale ( QDomElement rootElement , QString subTagName , QLocale locale )
{
QDomNodeList subList = rootElement . elementsByTagName ( subTagName ) ;
QString lang = locale . name ( ) ;
if ( lang . length ( ) > 2 )
lang [ 2 ] = QLatin1Char ( ' - ' ) ;
if ( subList . count ( ) > 1 ) {
for ( int i = 0 ; i < subList . count ( ) ; i + + ) {
QDomNode node = subList . at ( i ) ;
QDomElement element = node . toElement ( ) ;
QString configLang = element . attribute ( " xml:lang " , " " ) ;
if ( lang = = configLang | | ( configLang . length ( ) = = 2 & & configLang = = lang . left ( 2 ) ) )
return element . text ( ) ;
}
}
if ( subList . count ( ) > = 1 ) {
QDomElement element = subList . item ( 0 ) . toElement ( ) ;
return element . text ( ) ;
}
return QString ( ) ;
}
void UBGraphicsW3CWidgetItem : : copyItemParameters ( UBItem * copy ) const
{
UBGraphicsW3CWidgetItem * cp = dynamic_cast < UBGraphicsW3CWidgetItem * > ( copy ) ;
if ( cp )
{
cp - > setPos ( this - > pos ( ) ) ;
cp - > setTransform ( this - > transform ( ) ) ;
cp - > setFlag ( QGraphicsItem : : ItemIsMovable , true ) ;
cp - > setFlag ( QGraphicsItem : : ItemIsSelectable , true ) ;
cp - > setData ( UBGraphicsItemData : : ItemLayerType , this - > data ( UBGraphicsItemData : : ItemLayerType ) ) ;
cp - > setData ( UBGraphicsItemData : : ItemLocked , this - > data ( UBGraphicsItemData : : ItemLocked ) ) ;
cp - > setSourceUrl ( this - > sourceUrl ( ) ) ;
cp - > resize ( this - > size ( ) ) ;
foreach ( QString key , UBGraphicsWidgetItem : : preferences ( ) . keys ( ) )
{
cp - > setPreference ( key , UBGraphicsWidgetItem : : preferences ( ) . value ( key ) ) ;
}
foreach ( QString key , mDatastore . keys ( ) )
{
cp - > setDatastoreEntry ( key , mDatastore . value ( key ) ) ;
}
}
}