2010-10-14 20:34:46 +02:00
/*
* Copyright 2009 by Alan Alpert < alan . alpert @ nokia . com >
* Copyright 2010 by Ménard Alexis < menard @ kde . org >
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation ; either version 2 , 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 Library General Public
* License along with this program ; if not , write to the
* Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
# include <QDeclarativeComponent>
# include <QDeclarativeContext>
# include <QDeclarativeEngine>
# include <QDeclarativeExpression>
2010-10-22 12:12:35 +02:00
# include <QFile>
2010-10-14 20:34:46 +02:00
# include <QGraphicsLinearLayout>
# include <QScriptEngine>
# include <QScriptValueIterator>
# include <QTimer>
2010-10-22 12:12:35 +02:00
# include <QUiLoader>
# include <QWidget>
2010-10-14 20:34:46 +02:00
# include <KConfigGroup>
# include <KDebug>
# include <KGlobalSettings>
# include <Plasma/Applet>
# include <Plasma/DeclarativeWidget>
# include <Plasma/Extender>
# include <Plasma/ExtenderItem>
# include <Plasma/FrameSvg>
# include <Plasma/Package>
# include <Plasma/PopupApplet>
# include <Plasma/Svg>
# include "plasmoid/declarativeappletscript.h"
# include "plasmoid/appletinterface.h"
# include "plasmoid/themedsvg.h"
# include "common/scriptenv.h"
2012-03-01 22:49:34 +01:00
# include "declarative/declarativeitemcontainer_p.h"
2010-10-21 19:39:05 +02:00
# include "declarative/packageaccessmanagerfactory.h"
2010-10-14 20:34:46 +02:00
# include "simplebindings/bytearrayclass.h"
2011-04-07 23:27:05 +02:00
//not pretty but only way to avoid a double Q_DECLARE_METATYPE(QVariant) in dataengine.h
# define DECLARATIVE_BINDING
# include "simplebindings/dataengine.h"
2010-10-14 20:34:46 +02:00
# include "simplebindings/dataenginereceiver.h"
2011-04-07 23:27:05 +02:00
2010-10-14 20:34:46 +02:00
K_EXPORT_PLASMA_APPLETSCRIPTENGINE ( declarativeappletscript , DeclarativeAppletScript )
QScriptValue constructIconClass ( QScriptEngine * engine ) ;
QScriptValue constructKUrlClass ( QScriptEngine * engine ) ;
void registerSimpleAppletMetaTypes ( QScriptEngine * engine ) ;
DeclarativeAppletScript : : DeclarativeAppletScript ( QObject * parent , const QVariantList & args )
: AbstractJsAppletScript ( parent , args ) ,
2011-09-22 18:27:55 +02:00
m_interface ( 0 ) ,
2010-10-14 20:34:46 +02:00
m_engine ( 0 ) ,
2010-10-21 22:37:47 +02:00
m_env ( 0 ) ,
m_auth ( this )
2010-10-14 20:34:46 +02:00
{
Q_UNUSED ( args ) ;
}
DeclarativeAppletScript : : ~ DeclarativeAppletScript ( )
{
}
bool DeclarativeAppletScript : : init ( )
{
m_declarativeWidget = new Plasma : : DeclarativeWidget ( applet ( ) ) ;
m_declarativeWidget - > setInitializationDelayed ( true ) ;
2012-03-01 22:49:34 +01:00
connect ( m_declarativeWidget , SIGNAL ( finished ( ) ) , this , SLOT ( qmlCreationFinished ( ) ) ) ;
2011-11-02 14:48:41 +01:00
KGlobal : : locale ( ) - > insertCatalog ( " plasma_applet_ " % description ( ) . pluginName ( ) ) ;
2010-10-20 22:55:35 +02:00
2010-10-21 19:39:05 +02:00
//make possible to import extensions from the package
//FIXME: probably to be removed, would make possible to use native code from within the package :/
2010-12-08 23:45:45 +01:00
//m_declarativeWidget->engine()->addImportPath(package()->path()+"/contents/imports");
2010-10-20 22:55:35 +02:00
2011-02-07 21:29:08 +01:00
//use our own custom network access manager that will access Plasma packages and to manage security (i.e. deny access to remote stuff when the proper extension isn't enabled
2011-06-15 14:18:06 +02:00
QDeclarativeEngine * engine = m_declarativeWidget - > engine ( ) ;
QDeclarativeNetworkAccessManagerFactory * factory = engine - > networkAccessManagerFactory ( ) ;
engine - > setNetworkAccessManagerFactory ( 0 ) ;
delete factory ;
engine - > setNetworkAccessManagerFactory ( new PackageAccessManagerFactory ( package ( ) , & m_auth ) ) ;
2010-10-21 19:39:05 +02:00
2010-10-14 20:34:46 +02:00
m_declarativeWidget - > setQmlPath ( mainScript ( ) ) ;
2010-10-15 20:56:30 +02:00
if ( ! m_declarativeWidget - > engine ( ) | | ! m_declarativeWidget - > engine ( ) - > rootContext ( ) | | ! m_declarativeWidget - > engine ( ) - > rootContext ( ) - > isValid ( ) | | m_declarativeWidget - > mainComponent ( ) - > isError ( ) ) {
QString reason ;
foreach ( QDeclarativeError error , m_declarativeWidget - > mainComponent ( ) - > errors ( ) ) {
reason + = error . toString ( ) ;
}
setFailedToLaunch ( true , reason ) ;
2010-10-14 20:34:46 +02:00
return false ;
}
Plasma : : Applet * a = applet ( ) ;
Plasma : : PopupApplet * pa = qobject_cast < Plasma : : PopupApplet * > ( a ) ;
2011-02-20 19:45:12 +01:00
Plasma : : Containment * cont = qobject_cast < Plasma : : Containment * > ( a ) ;
2010-10-14 20:34:46 +02:00
if ( pa ) {
pa - > setPopupIcon ( a - > icon ( ) ) ;
pa - > setGraphicsWidget ( m_declarativeWidget ) ;
} else {
QGraphicsLinearLayout * lay = new QGraphicsLinearLayout ( a ) ;
lay - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
lay - > addItem ( m_declarativeWidget ) ;
}
2011-02-20 19:45:12 +01:00
if ( pa ) {
m_interface = new PopupAppletInterface ( this ) ;
} else if ( cont ) {
m_interface = new ContainmentInterface ( this ) ;
//fail? so it's a normal Applet
} else {
m_interface = new AppletInterface ( this ) ;
}
2010-10-14 20:34:46 +02:00
connect ( applet ( ) , SIGNAL ( extenderItemRestored ( Plasma : : ExtenderItem * ) ) ,
this , SLOT ( extenderItemRestored ( Plasma : : ExtenderItem * ) ) ) ;
connect ( applet ( ) , SIGNAL ( activate ( ) ) ,
this , SLOT ( activate ( ) ) ) ;
2011-04-07 22:37:34 +02:00
setupObjects ( ) ;
2010-10-14 20:34:46 +02:00
return true ;
}
2012-03-01 22:49:34 +01:00
void DeclarativeAppletScript : : qmlCreationFinished ( )
{
//If it's a popupapplet and the root object has a "compactRepresentation" component, use that instead of the icon
Plasma : : Applet * a = applet ( ) ;
Plasma : : PopupApplet * pa = qobject_cast < Plasma : : PopupApplet * > ( a ) ;
if ( pa ) {
QDeclarativeComponent * iconComponent = m_declarativeWidget - > rootObject ( ) - > property ( " compactRepresentation " ) . value < QDeclarativeComponent * > ( ) ;
if ( iconComponent ) {
QDeclarativeItem * declarativeIcon = qobject_cast < QDeclarativeItem * > ( iconComponent - > create ( m_declarativeWidget - > engine ( ) - > rootContext ( ) ) ) ;
if ( declarativeIcon ) {
pa - > setPopupIcon ( QIcon ( ) ) ;
QGraphicsLinearLayout * lay = new QGraphicsLinearLayout ( a ) ;
lay - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
DeclarativeItemContainer * declarativeItemContainer = new DeclarativeItemContainer ( a ) ;
lay - > addItem ( declarativeItemContainer ) ;
declarativeItemContainer - > setDeclarativeItem ( declarativeIcon ) ;
} else {
pa - > setPopupIcon ( a - > icon ( ) ) ;
}
} else {
pa - > setPopupIcon ( a - > icon ( ) ) ;
}
}
}
2010-10-14 20:34:46 +02:00
void DeclarativeAppletScript : : collectGarbage ( )
{
2011-05-17 16:39:15 +02:00
if ( ! m_engine ) {
return ;
}
2010-10-14 20:34:46 +02:00
m_engine - > collectGarbage ( ) ;
}
QString DeclarativeAppletScript : : filePath ( const QString & type , const QString & file ) const
{
const QString path = m_env - > filePathFromScriptContext ( type . toLocal8Bit ( ) . constData ( ) , file ) ;
if ( ! path . isEmpty ( ) ) {
return path ;
}
return package ( ) - > filePath ( type . toLocal8Bit ( ) . constData ( ) , file ) ;
}
void DeclarativeAppletScript : : configChanged ( )
{
if ( ! m_env ) {
return ;
}
m_env - > callEventListeners ( " configchanged " ) ;
}
2010-10-22 12:12:35 +02:00
QScriptValue DeclarativeAppletScript : : loadui ( QScriptContext * context , QScriptEngine * engine )
{
if ( context - > argumentCount ( ) ! = 1 ) {
return context - > throwError ( i18n ( " loadui() takes one argument " ) ) ;
}
QString filename = context - > argument ( 0 ) . toString ( ) ;
QFile f ( filename ) ;
if ( ! f . open ( QIODevice : : ReadOnly ) ) {
return context - > throwError ( i18n ( " Unable to open '%1' " , filename ) ) ;
}
QUiLoader loader ;
QWidget * w = loader . load ( & f ) ;
f . close ( ) ;
return engine - > newQObject ( w , QScriptEngine : : AutoOwnership ) ;
}
2010-10-14 20:34:46 +02:00
QScriptValue DeclarativeAppletScript : : newPlasmaSvg ( QScriptContext * context , QScriptEngine * engine )
{
if ( context - > argumentCount ( ) = = 0 ) {
return context - > throwError ( i18n ( " Constructor takes at least 1 argument " ) ) ;
}
const QString filename = context - > argument ( 0 ) . toString ( ) ;
Plasma : : Svg * svg = new ThemedSvg ( 0 ) ;
svg - > setImagePath ( ThemedSvg : : findSvg ( engine , filename ) ) ;
QScriptValue obj = engine - > newQObject ( svg ) ;
ScriptEnv : : registerEnums ( obj , * svg - > metaObject ( ) ) ;
return obj ;
}
QScriptValue DeclarativeAppletScript : : variantToScriptValue ( QVariant var )
{
2011-05-17 16:39:15 +02:00
if ( ! m_engine ) {
return QScriptValue ( ) ;
}
2010-10-14 20:34:46 +02:00
return m_engine - > newVariant ( var ) ;
}
QScriptValue DeclarativeAppletScript : : newPlasmaFrameSvg ( QScriptContext * context , QScriptEngine * engine )
{
if ( context - > argumentCount ( ) = = 0 ) {
return context - > throwError ( i18n ( " Constructor takes at least 1 argument " ) ) ;
}
QString filename = context - > argument ( 0 ) . toString ( ) ;
bool parentedToApplet = false ;
QGraphicsWidget * parent = extractParent ( context , engine , 1 , & parentedToApplet ) ;
Plasma : : FrameSvg * frameSvg = new ThemedFrameSvg ( parent ) ;
frameSvg - > setImagePath ( ThemedSvg : : findSvg ( engine , filename ) ) ;
QScriptValue obj = engine - > newQObject ( frameSvg ) ;
ScriptEnv : : registerEnums ( obj , * frameSvg - > metaObject ( ) ) ;
return obj ;
}
QScriptValue DeclarativeAppletScript : : newPlasmaExtenderItem ( QScriptContext * context , QScriptEngine * engine )
{
Plasma : : Extender * extender = 0 ;
if ( context - > argumentCount ( ) > 0 ) {
extender = qobject_cast < Plasma : : Extender * > ( context - > argument ( 0 ) . toQObject ( ) ) ;
}
if ( ! extender ) {
AppletInterface * interface = AppletInterface : : extract ( engine ) ;
if ( ! interface ) {
engine - > undefinedValue ( ) ;
}
extender = interface - > extender ( ) ;
}
Plasma : : ExtenderItem * extenderItem = new Plasma : : ExtenderItem ( extender ) ;
QScriptValue fun = engine - > newQObject ( extenderItem ) ;
ScriptEnv : : registerEnums ( fun , * extenderItem - > metaObject ( ) ) ;
return fun ;
}
QGraphicsWidget * DeclarativeAppletScript : : extractParent ( QScriptContext * context , QScriptEngine * engine ,
int argIndex , bool * parentedToApplet )
{
if ( parentedToApplet ) {
* parentedToApplet = false ;
}
QGraphicsWidget * parent = 0 ;
if ( context - > argumentCount ( ) > = argIndex ) {
parent = qobject_cast < QGraphicsWidget * > ( context - > argument ( argIndex ) . toQObject ( ) ) ;
}
if ( ! parent ) {
AppletInterface * interface = AppletInterface : : extract ( engine ) ;
if ( ! interface ) {
return 0 ;
}
//kDebug() << "got the applet!";
parent = interface - > applet ( ) ;
if ( parentedToApplet ) {
* parentedToApplet = true ;
}
}
return parent ;
}
2011-06-09 14:31:03 +02:00
void DeclarativeAppletScript : : callPlasmoidFunction ( const QString & functionName , const QScriptValueList & args , ScriptEnv * env )
{
if ( ! m_env ) {
m_env = ScriptEnv : : findScriptEnv ( m_engine ) ;
}
if ( env ) {
QScriptValue func = m_self . property ( functionName ) ;
m_env - > callFunction ( func , args , m_self ) ;
}
}
2010-10-14 20:34:46 +02:00
void DeclarativeAppletScript : : constraintsEvent ( Plasma : : Constraints constraints )
{
if ( constraints & Plasma : : FormFactorConstraint ) {
emit formFactorChanged ( ) ;
}
if ( constraints & Plasma : : LocationConstraint ) {
emit locationChanged ( ) ;
}
if ( constraints & Plasma : : ContextConstraint ) {
emit contextChanged ( ) ;
}
}
void DeclarativeAppletScript : : popupEvent ( bool popped )
{
if ( ! m_env ) {
return ;
}
QScriptValueList args ;
args < < popped ;
m_env - > callEventListeners ( " popupEvent " , args ) ;
}
void DeclarativeAppletScript : : dataUpdated ( const QString & name , const Plasma : : DataEngine : : Data & data )
{
2011-05-17 16:39:15 +02:00
if ( ! m_engine ) {
return ;
}
2010-10-14 20:34:46 +02:00
QScriptValueList args ;
args < < m_engine - > toScriptValue ( name ) < < m_engine - > toScriptValue ( data ) ;
m_env - > callEventListeners ( " dataUpdated " , args ) ;
}
void DeclarativeAppletScript : : extenderItemRestored ( Plasma : : ExtenderItem * item )
{
if ( ! m_env ) {
return ;
}
2011-05-17 16:39:15 +02:00
if ( ! m_engine ) {
return ;
}
2010-10-14 20:34:46 +02:00
QScriptValueList args ;
args < < m_engine - > newQObject ( item , QScriptEngine : : AutoOwnership , QScriptEngine : : PreferExistingWrapperObject ) ;
m_env - > callEventListeners ( " initExtenderItem " , args ) ;
}
void DeclarativeAppletScript : : activate ( )
{
if ( ! m_env ) {
return ;
}
m_env - > callEventListeners ( " activate " ) ;
}
void DeclarativeAppletScript : : executeAction ( const QString & name )
{
if ( ! m_env ) {
return ;
}
const QString func ( " action_ " + name ) ;
2011-06-09 14:31:03 +02:00
if ( ! m_env - > callEventListeners ( func ) ) {
callPlasmoidFunction ( func , QScriptValueList ( ) , m_env ) ;
}
2010-10-14 20:34:46 +02:00
}
bool DeclarativeAppletScript : : include ( const QString & path )
{
return m_env - > include ( path ) ;
}
ScriptEnv * DeclarativeAppletScript : : scriptEnv ( )
{
return m_env ;
}
void DeclarativeAppletScript : : setupObjects ( )
{
2011-04-07 22:37:34 +02:00
m_engine = m_declarativeWidget - > scriptEngine ( ) ;
2011-05-17 16:39:15 +02:00
if ( ! m_engine ) {
return ;
}
2011-04-07 22:37:34 +02:00
connect ( m_engine , SIGNAL ( signalHandlerException ( const QScriptValue & ) ) ,
this , SLOT ( signalHandlerException ( const QScriptValue & ) ) ) ;
delete m_env ;
m_env = new ScriptEnv ( this , m_engine ) ;
QScriptValue global = m_engine - > globalObject ( ) ;
2010-10-14 20:34:46 +02:00
2011-12-05 22:40:16 +01:00
QScriptValue v = m_engine - > newVariant ( QVariant : : fromValue ( * applet ( ) - > package ( ) ) ) ;
global . setProperty ( " __plasma_package " , v ,
QScriptValue : : ReadOnly | QScriptValue : : Undeletable | QScriptValue : : SkipInEnumeration ) ;
2010-10-14 20:34:46 +02:00
m_self = m_engine - > newQObject ( m_interface ) ;
m_self . setScope ( global ) ;
global . setProperty ( " plasmoid " , m_self ) ;
m_env - > addMainObjectProperties ( m_self ) ;
QScriptValue args = m_engine - > newArray ( ) ;
int i = 0 ;
foreach ( const QVariant & arg , applet ( ) - > startupArguments ( ) ) {
args . setProperty ( i , m_engine - > newVariant ( arg ) ) ;
+ + i ;
}
global . setProperty ( " startupArguments " , args ) ;
2010-10-22 12:12:35 +02:00
// Add a global loadui method for ui files
QScriptValue fun = m_engine - > newFunction ( DeclarativeAppletScript : : loadui ) ;
global . setProperty ( " loadui " , fun ) ;
2011-02-25 22:11:11 +01:00
ScriptEnv : : registerEnums ( global , AppletInterface : : staticMetaObject ) ;
2010-10-14 20:34:46 +02:00
global . setProperty ( " dataEngine " , m_engine - > newFunction ( DeclarativeAppletScript : : dataEngine ) ) ;
global . setProperty ( " service " , m_engine - > newFunction ( DeclarativeAppletScript : : service ) ) ;
2010-10-23 19:30:10 +02:00
global . setProperty ( " loadService " , m_engine - > newFunction ( DeclarativeAppletScript : : loadService ) ) ;
2010-10-14 20:34:46 +02:00
//Add stuff from Qt
2011-04-07 23:27:05 +02:00
//TODO: move to libkdeclarative?
2010-10-14 20:34:46 +02:00
ByteArrayClass * baClass = new ByteArrayClass ( m_engine ) ;
global . setProperty ( " ByteArray " , baClass - > constructor ( ) ) ;
// Add stuff from Plasma
global . setProperty ( " Svg " , m_engine - > newFunction ( DeclarativeAppletScript : : newPlasmaSvg ) ) ;
global . setProperty ( " FrameSvg " , m_engine - > newFunction ( DeclarativeAppletScript : : newPlasmaFrameSvg ) ) ;
global . setProperty ( " ExtenderItem " , m_engine - > newFunction ( DeclarativeAppletScript : : newPlasmaExtenderItem ) ) ;
2011-04-07 22:37:34 +02:00
if ( ! m_env - > importExtensions ( description ( ) , m_self , m_auth ) ) {
return ;
}
registerSimpleAppletMetaTypes ( m_engine ) ;
QTimer : : singleShot ( 0 , this , SLOT ( configChanged ( ) ) ) ;
2010-10-14 20:34:46 +02:00
}
QScriptValue DeclarativeAppletScript : : dataEngine ( QScriptContext * context , QScriptEngine * engine )
{
if ( context - > argumentCount ( ) ! = 1 ) {
return context - > throwError ( i18n ( " dataEngine() takes one argument " ) ) ;
}
AppletInterface * interface = AppletInterface : : extract ( engine ) ;
if ( ! interface ) {
return context - > throwError ( i18n ( " Could not extract the Applet " ) ) ;
}
const QString dataEngineName = context - > argument ( 0 ) . toString ( ) ;
Plasma : : DataEngine * dataEngine = interface - > dataEngine ( dataEngineName ) ;
QScriptValue v = engine - > newQObject ( dataEngine , QScriptEngine : : QtOwnership , QScriptEngine : : PreferExistingWrapperObject ) ;
v . setProperty ( " connectSource " , engine - > newFunction ( DataEngineReceiver : : connectSource ) ) ;
2011-04-04 14:42:25 +02:00
v . setProperty ( " connectAllSources " , engine - > newFunction ( DataEngineReceiver : : connectAllSources ) ) ;
2010-10-14 20:34:46 +02:00
v . setProperty ( " disconnectSource " , engine - > newFunction ( DataEngineReceiver : : disconnectSource ) ) ;
return v ;
}
QScriptValue DeclarativeAppletScript : : service ( QScriptContext * context , QScriptEngine * engine )
{
if ( context - > argumentCount ( ) ! = 2 ) {
return context - > throwError ( i18n ( " service() takes two arguments " ) ) ;
}
QString dataEngine = context - > argument ( 0 ) . toString ( ) ;
AppletInterface * interface = AppletInterface : : extract ( engine ) ;
if ( ! interface ) {
return context - > throwError ( i18n ( " Could not extract the Applet " ) ) ;
}
Plasma : : DataEngine * data = interface - > dataEngine ( dataEngine ) ;
QString source = context - > argument ( 1 ) . toString ( ) ;
Plasma : : Service * service = data - > serviceForSource ( source ) ;
//kDebug( )<< "lets try to get" << source << "from" << dataEngine;
return engine - > newQObject ( service , QScriptEngine : : AutoOwnership ) ;
}
2010-10-23 19:30:10 +02:00
QScriptValue DeclarativeAppletScript : : loadService ( QScriptContext * context , QScriptEngine * engine )
{
if ( context - > argumentCount ( ) ! = 1 ) {
return context - > throwError ( i18n ( " service() takes one argument " ) ) ;
}
QString pluginName = context - > argument ( 0 ) . toString ( ) ;
AppletInterface * interface = AppletInterface : : extract ( engine ) ;
if ( ! interface ) {
return context - > throwError ( i18n ( " Could not extract the Applet " ) ) ;
}
Plasma : : Service * service = Plasma : : Service : : load ( pluginName , interface ) ;
//kDebug( )<< "lets try to get" << source << "from" << dataEngine;
return engine - > newQObject ( service , QScriptEngine : : AutoOwnership ) ;
}
2011-06-09 14:31:03 +02:00
QList < QAction * > DeclarativeAppletScript : : contextualActions ( )
{
2011-09-22 18:27:55 +02:00
if ( ! m_interface ) {
return QList < QAction * > ( ) ;
}
2011-06-09 14:31:03 +02:00
return m_interface - > contextualActions ( ) ;
}
2011-02-20 19:45:12 +01:00
QScriptEngine * DeclarativeAppletScript : : engine ( ) const
{
return m_engine ;
}
2010-10-14 20:34:46 +02:00
void DeclarativeAppletScript : : signalHandlerException ( const QScriptValue & exception )
{
kWarning ( ) < < " Exception caught: " < < exception . toVariant ( ) ;
}
# include "declarativeappletscript.moc"