/*
* This program 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 , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program 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 this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "UBAbstractWidget.h"
# include <QtNetwork>
# include <QtXml>
# include "frameworks/UBFileSystemUtils.h"
# include "core/UBApplicationController.h"
# include "core/UBApplication.h"
# include "core/UBSettings.h"
# include "network/UBNetworkAccessManager.h"
# include "api/UBWidgetUniboardAPI.h"
# include "web/UBWebPage.h"
# include "web/UBWebKitUtils.h"
# include "web/UBWebController.h"
# include "core/memcheck.h"
QStringList UBAbstractWidget : : sInlineJavaScripts ;
bool UBAbstractWidget : : sInlineJavaScriptLoaded = false ;
UBAbstractWidget : : UBAbstractWidget ( const QUrl & pWidgetUrl , QWidget * parent )
: UBRoutedMouseEventWebView ( parent )
, mWidgetUrl ( pWidgetUrl )
, mIsResizable ( false )
, mInitialLoadDone ( false )
, mLoadIsErronous ( false )
, mIsFreezable ( true )
, mCanBeContent ( 0 )
, mCanBeTool ( 0 )
, mIsFrozen ( false )
, mIsTakingSnapshot ( false )
{
setPage ( new UBWebPage ( this ) ) ;
QWebView : : settings ( ) - > setAttribute ( QWebSettings : : PluginsEnabled , true ) ;
QWebView : : settings ( ) - > setAttribute ( QWebSettings : : LocalStorageDatabaseEnabled , true ) ;
QWebView : : page ( ) - > setNetworkAccessManager ( UBNetworkAccessManager : : defaultAccessManager ( ) ) ;
setAutoFillBackground ( false ) ;
QPalette pagePalette = QWebView : : page ( ) - > palette ( ) ;
pagePalette . setBrush ( QPalette : : Base , QBrush ( Qt : : transparent ) ) ;
pagePalette . setBrush ( QPalette : : Window , QBrush ( Qt : : transparent ) ) ;
QWebView : : page ( ) - > setPalette ( pagePalette ) ;
QPalette viewPalette = palette ( ) ;
pagePalette . setBrush ( QPalette : : Base , QBrush ( Qt : : transparent ) ) ;
viewPalette . setBrush ( QPalette : : Window , QBrush ( Qt : : transparent ) ) ;
setPalette ( viewPalette ) ;
connect ( QWebView : : page ( ) - > mainFrame ( ) , SIGNAL ( javaScriptWindowObjectCleared ( ) ) , this , SLOT ( javaScriptWindowObjectCleared ( ) ) ) ;
connect ( QWebView : : page ( ) , SIGNAL ( geometryChangeRequested ( const QRect & ) ) , this , SIGNAL ( geometryChangeRequested ( const QRect & ) ) ) ;
connect ( QWebView : : page ( ) , SIGNAL ( loadFinished ( bool ) ) , this , SLOT ( mainFrameLoadFinished ( bool ) ) ) ;
setMouseTracking ( true ) ;
}
bool UBAbstractWidget : : canBeContent ( )
{
// if we under MAC OS
# if defined(Q_OS_MAC)
return mCanBeContent & UBAbstractWidget : : type_MAC ;
# endif
// if we under UNIX OS
# if defined(Q_OS_UNIX)
return mCanBeContent & UBAbstractWidget : : type_UNIX ;
# endif
// if we under WINDOWS OS
# if defined(Q_OS_WIN)
return mCanBeContent & UBAbstractWidget : : type_WIN ;
# endif
}
bool UBAbstractWidget : : canBeTool ( )
{
// if we under MAC OS
# if defined(Q_OS_MAC)
return mCanBeTool & UBAbstractWidget : : type_MAC ;
# endif
// if we under UNIX OS
# if defined(Q_OS_UNIX)
return mCanBeTool & UBAbstractWidget : : type_UNIX ;
# endif
// if we under WINDOWS OS
# if defined(Q_OS_WIN)
return mCanBeTool & UBAbstractWidget : : type_WIN ;
# endif
}
UBAbstractWidget : : ~ UBAbstractWidget ( )
{
// NOOP
}
void UBAbstractWidget : : loadMainHtml ( )
{
QWebView : : load ( mMainHtmlUrl ) ;
}
bool UBAbstractWidget : : event ( QEvent * event )
{
if ( event - > type ( ) = = QEvent : : ContextMenu )
{
event - > accept ( ) ;
return true ;
} else {
return QWebView : : event ( event ) ;
}
}
void UBAbstractWidget : : mainFrameLoadFinished ( bool ok )
{
mInitialLoadDone = true ;
mLoadIsErronous = ! ok ;
update ( ) ;
}
bool UBAbstractWidget : : hasEmbededObjects ( )
{
if ( QWebView : : page ( ) - > mainFrame ( ) )
{
QList < UBWebKitUtils : : HtmlObject > htmlObjects = UBWebKitUtils : : objectsInFrame ( QWebView : : page ( ) - > mainFrame ( ) ) ;
return htmlObjects . length ( ) > 0 ;
}
return false ;
}
bool UBAbstractWidget : : hasEmbededFlash ( )
{
if ( hasEmbededObjects ( ) )
{
return QWebView : : page ( ) - > mainFrame ( ) - > toHtml ( ) . contains ( " application/x-shockwave-flash " ) ;
}
else
{
return false ;
}
}
void UBAbstractWidget : : resize ( qreal width , qreal height )
{
QWebView : : page ( ) - > setViewportSize ( QSize ( width , height ) ) ;
QWebView : : setFixedSize ( QSize ( width , height ) ) ;
}
QString UBAbstractWidget : : 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 ;
}
QString UBAbstractWidget : : 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 ;
}
int UBAbstractWidget : : 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 ;
}
}
void UBAbstractWidget : : mousePressEvent ( QMouseEvent * event )
{
if ( mIsFrozen )
{
event - > accept ( ) ;
return ;
}
UBRoutedMouseEventWebView : : mousePressEvent ( event ) ;
mMouseIsPressed = true ;
}
void UBAbstractWidget : : mouseMoveEvent ( QMouseEvent * event )
{
if ( mIsFrozen )
{
event - > accept ( ) ;
return ;
}
// TODO UB 4.x fix web kit mouse move routing
if ( mFirstReleaseAfterMove )
{
mFirstReleaseAfterMove = false ;
}
else
{
UBRoutedMouseEventWebView : : mouseMoveEvent ( event ) ;
}
}
void UBAbstractWidget : : mouseReleaseEvent ( QMouseEvent * event )
{
if ( mIsFrozen )
{
event - > accept ( ) ;
return ;
}
UBRoutedMouseEventWebView : : mouseReleaseEvent ( event ) ;
mMouseIsPressed = false ;
mFirstReleaseAfterMove = true ;
}
QWebView * UBAbstractWidget : : createWindow ( QWebPage : : WebWindowType type )
{
if ( type = = QWebPage : : WebBrowserWindow )
{
UBApplication : : applicationController - > showInternet ( ) ;
return UBApplication : : webController - > createNewTab ( ) ;
}
else
{
return this ;
}
}
void UBAbstractWidget : : injectInlineJavaScript ( )
{
if ( ! sInlineJavaScriptLoaded )
{
sInlineJavaScripts = UBApplication : : applicationController - > widgetInlineJavaScripts ( ) ;
sInlineJavaScriptLoaded = true ;
}
foreach ( QString script , sInlineJavaScripts )
{
QWebView : : page ( ) - > mainFrame ( ) - > evaluateJavaScript ( script ) ;
}
}
void UBAbstractWidget : : javaScriptWindowObjectCleared ( )
{
injectInlineJavaScript ( ) ;
}
void UBAbstractWidget : : paintEvent ( QPaintEvent * event )
{
if ( mIsFrozen )
{
QPainter p ( this ) ;
p . drawPixmap ( 0 , 0 , mSnapshot ) ;
}
else if ( mIsTakingSnapshot | | ( mInitialLoadDone & & ! mLoadIsErronous ) )
{
QWebView : : paintEvent ( event ) ;
}
else
{
QPainter p ( this ) ;
QString message ;
if ( mLoadIsErronous )
message = tr ( " Cannot load content " ) ;
else
message = tr ( " Loading ... " ) ;
p . setFont ( QFont ( " Arial " , 12 ) ) ;
QFontMetrics fm = p . fontMetrics ( ) ;
QRect txtBoundingRect = fm . boundingRect ( message ) ;
txtBoundingRect . moveCenter ( rect ( ) . center ( ) ) ;
txtBoundingRect . adjust ( - 10 , - 5 , 10 , 5 ) ;
p . setPen ( Qt : : NoPen ) ;
p . setBrush ( UBSettings : : paletteColor ) ;
p . drawRoundedRect ( txtBoundingRect , 3 , 3 ) ;
p . setPen ( Qt : : white ) ;
p . drawText ( rect ( ) , Qt : : AlignCenter , message ) ;
}
}
QPixmap UBAbstractWidget : : takeSnapshot ( )
{
mIsTakingSnapshot = true ;
QPixmap pix ( size ( ) ) ;
pix . fill ( Qt : : transparent ) ;
render ( & pix ) ;
mIsTakingSnapshot = false ;
return pix ;
}
void UBAbstractWidget : : setSnapshot ( const QPixmap & pix )
{
mSnapshot = pix ;
}
void UBAbstractWidget : : freeze ( )
{
QPixmap pix = takeSnapshot ( ) ;
mIsFrozen = true ;
setSnapshot ( pix ) ;
update ( ) ;
}
void UBAbstractWidget : : unFreeze ( )
{
mIsFrozen = false ;
update ( ) ;
}