You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeaddons/kate/kjswrapper/plugin_katekjswrapper.cpp

438 lines
16 KiB

/* This file is part of the KDE project
Copyright (C) 2004 Joseph Wenninger <jowenn@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
//BEGIN includes
#include "plugin_katekjswrapper.h"
#include "plugin_katekjswrapper.moc"
#include "bindings.h"
#include <kjsembed/kjsembedpart.h>
#include <kjsembed/jssecuritypolicy.h>
#include <kjsembed/jsfactory.h>
#include <kjsembed/jsconsolewidget.h>
#include <kjs/interpreter.h>
#include <kjs/value.h>
#include <kjs/object.h>
#include <kgenericfactory.h>
#include <kdebug.h>
#include <tqlayout.h>
#include <kstandarddirs.h>
#include <kate/mainwindow.h>
#include <kate/toolviewmanager.h>
#include <kdockwidget.h>
#include <tqvbox.h>
//END includes
K_EXPORT_COMPONENT_FACTORY( katekjswrapperplugin, KGenericFactory<PluginKateKJSWrapper>( "katekjswrapper" ) )
PluginKateKJSWrapperView::~PluginKateKJSWrapperView() {
}
void PluginKateKJSWrapperView::removeFromWindow() {
kdDebug()<<"PluginKateKJSWrapperView::removeFromWindow"<<endl;
for (TQValueList<TQGuardedPtr<KMDI::ToolViewAccessor> >::iterator it=toolviews.begin();it!=toolviews.end();it=toolviews.begin()) {
kdDebug()<<"removeFromWindow: removing a toolview"<<endl;
KMDI::ToolViewAccessor* tva=(*it);
toolviews.remove(it);
win->toolViewManager()->removeToolView (tva);
}
win->guiFactory()->removeClient (this);
}
PluginKateKJSWrapper::PluginKateKJSWrapper( TQObject* parent, const char* name, const TQStringList& list)
: Kate::Plugin ( (Kate::Application *)parent, name ) {
m_views.setAutoDelete(true);
m_scriptname=list[0];
m_kateAppBindings=new Kate::JS::Bindings(this);
KJSEmbed::JSSecurityPolicy::setDefaultPolicy( KJSEmbed::JSSecurityPolicy::CapabilityAll );
m_part = new KJSEmbed::KJSEmbedPart(this);
KJS::Interpreter *js = m_part->interpreter();
KJSEmbed::JSFactory *factory=m_part->factory();
/* factories for kate app classes */
factory->addTQObjectPlugin("Kate::Application",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::DocumentManager",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::MainWindow",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::PluginManager",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::InitPluginManager",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::ProjectManager",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::Project",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::ViewManager",m_kateAppBindings);
factory->addTQObjectPlugin("Kate::View",m_kateAppBindings);
/* toplevel objects*/
KJS::Object appobj=m_part->addObject(Kate::application(),"KATE");
js->globalObject().put( js->globalExec(), "addConfigPage", KJS::Object(new Kate::JS::Management(js->globalExec(),Kate::JS::Management::AddConfigPage,this )));
js->globalObject().put( js->globalExec(), "setConfigPages", KJS::Object(new Kate::JS::Management(js->globalExec(),Kate::JS::Management::SetConfigPages,this )));
js->globalObject().put( js->globalExec(), "removeConfigPage", KJS::Object(new Kate::JS::Management(js->globalExec(),Kate::JS::Management::RemoveConfigPage,this )));
js->globalObject().put( js->globalExec(), "setWindowConfiguration", KJS::Object(new Kate::JS::Management(js->globalExec(),Kate::JS::Management::SetWindowConfiguration,this )));
js->globalObject().put( js->globalExec(), "KJSConsole", KJS::Object(new Kate::JS::Management(js->globalExec(),Kate::JS::Management::KJSConsole,this )));
/* KJSEmbed::JSConsoleWidget *w=m_part->view();
w->show();
//w->show();*/
kdDebug()<<"m_scriptname="<<m_scriptname<<endl;
m_part->runFile(locate("appdata",TQString("plugins/%1/%2.js").tqarg(m_scriptname).tqarg(m_scriptname)));
//"/home/jowenn/development/kde/cvs/tdeaddons/kate/kjswrapper/samples/test1.js");
}
PluginKateKJSWrapper::~PluginKateKJSWrapper()
{
delete m_part;
m_part=0;
}
uint PluginKateKJSWrapper::configPages () const {
KJS::Interpreter *js = m_part->interpreter();
KJS::ExecState *exec=js->globalExec();
if (! (m_configPageFactories.isNull() || (m_configPageFactories.type()==KJS::NullType))) {
KJS::Object constrs=m_configPageFactories.toObject(exec);
if (!exec->hadException()) {
if (TQString(constrs.classInfo()->className)=="Array") {
kdDebug()<<"config page constructor array detected"<<endl;
uint size=constrs.get(exec,KJS::Identifier("length")).toInteger(exec);
if (exec->hadException()) {
exec->clearException();
kdDebug()<<"Error while retrieving array length"<<endl;
}
else return size;
} else return 1;
}
}
exec->clearException();
return 0;
}
static KJS::Object getObj(KJS::Interpreter *js, KJS::Value mightBeArray, int id) {
KJS::ExecState *exec=js->globalExec();
KJS::Object constrs=mightBeArray.toObject(exec);
KJS::Value constr;
if (!exec->hadException()) {
if (TQString(constrs.classInfo()->className)=="Array") {
kdDebug()<<"config page constructor array detected"<<endl;
constr=constrs.get(exec,id);
} else constr=mightBeArray;
}
return constr.toObject(js->globalExec());
}
TQString PluginKateKJSWrapper::configPageName(uint id) const {
if (id>=configPages()) return "";
KJS::Interpreter *js = m_part->interpreter();
KJS::Object constr=getObj(js,m_configPageFactories,id);
KJS::Value o=constr.get(js->globalExec(),KJS::Identifier("name"));
TQString retVal( o.toString(js->globalExec()).qstring() );
kdDebug()<<"=============================================================================================="<<endl;
kdDebug()<<"PluginKateKJSWrapper::configPageName: "<<retVal<<endl;
kdDebug()<<"=============================================================================================="<<endl;
js->globalExec()->clearException();
return retVal;
}
TQString PluginKateKJSWrapper::configPageFullName(uint id) const {
if (id>=configPages()) return "";
KJS::Interpreter *js = m_part->interpreter();
KJS::Object constr=getObj(js,m_configPageFactories,id);
KJS::Value o=constr.get(js->globalExec(),KJS::Identifier("fullName"));
TQString retVal( o.toString(js->globalExec()).qstring() );
kdDebug()<<"=============================================================================================="<<endl;
kdDebug()<<"PluginKateKJSWrapper::configPageFullName: "<<retVal<<endl;
kdDebug()<<"=============================================================================================="<<endl;
js->globalExec()->clearException();
return retVal;
}
TQPixmap PluginKateKJSWrapper::configPagePixmap (uint /*number = 0*/,
int /*size = KIcon::SizeSmall*/) const {
return 0;
}
Kate::PluginConfigPage* PluginKateKJSWrapper::configPage (uint id,
TQWidget *w, const char */*name*/) {
kdDebug()<<"PluginKateKJSWrapper::configPage"<<endl;
if (id>=configPages()) return 0;
KJS::Interpreter *js = m_part->interpreter();
KJS::Object constr=getObj(js,m_configPageFactories,id);
if (js->globalExec()->hadException()) {
kdDebug()<<"PluginKateKJSWrapper::configPage: exit 1"<<endl;
js->globalExec()->clearException();
return 0;
}
if (!constr.implementsConstruct()) {
kdWarning()<<"config page factory has to be an object constructor"<<endl;
return 0;
}
KateKJSWrapperConfigPage *p=new KateKJSWrapperConfigPage(constr,this,w);
return (Kate::PluginConfigPage*)p;
/*
KateKJSWrapperConfigPage* p = new KateKJSWrapperConfigPage(this, w);
//init
connect( p, TQT_SIGNAL(configPageApplyRequest(KateKJSWrapperConfigPage*)),
this, TQT_SLOT(applyConfig(KateKJSWrapperConfigPage*)) );
return (Kate::PluginConfigPage*);*/
}
static KMDI::ToolViewAccessor *createToolView(KJSEmbed::JSFactory *factory,KJS::Interpreter *js, Kate::MainWindow *winN,KJS::Object win,KJS::Object viewConstructor) {
KJS::List params;
KJS::ExecState *exec = js->globalExec();
params.append(win);
exec->clearException();
int dockPos;
if (!viewConstructor.implementsConstruct()) return 0;
KJS::Value dockPosV=viewConstructor.get(exec,KJS::Identifier("startPosition"));
if (exec->hadException()) {
dockPos=KDockWidget::DockLeft;
exec->clearException();
} else {
dockPos=dockPosV.toInteger(exec);
if (exec->hadException()) {
dockPos=KDockWidget::DockLeft;
exec->clearException();
}
}
TQString viewName;
KJS::Value viewNameV=viewConstructor.get(exec,KJS::Identifier("name"));
if (exec->hadException()) {
viewName="kjs_unknown";
exec->clearException();
} else {
viewName=TQString( viewNameV.toString(exec).qstring() );
if (exec->hadException()) {
viewName="kjs_unknown";
exec->clearException();
}
}
Kate::JS::ToolView *tv=new Kate::JS::ToolView(viewConstructor,exec,factory,params,viewName.utf8());
//params.append(factory->createProxy(exec,tv));
//KJS::Object otv=viewConstructor.construct(exec,params);
if (exec->hadException()) {
kdDebug()<<"Error while calling constructor"<<endl;
delete tv;
kdDebug()<<exec->exception().toString(exec).qstring()<<endl;
exec->clearException();
return 0;
}
KMDI::ToolViewAccessor *tva=winN->toolViewManager()->addToolView((KDockWidget::DockPosition)dockPos,tv,
tv->icon()?(*(tv->icon())):TQPixmap(),tv->caption());
kdDebug()<<"****************************************************************************************"<<endl;
kdDebug()<<"PluginKateKJSWrapper: Toolview has been added"<<endl;
kdDebug()<<"****************************************************************************************"<<endl;
return tva;
}
PluginKateKJSWrapperView *PluginKateKJSWrapper::getViewObject(Kate::MainWindow *win) {
PluginKateKJSWrapperView * view=m_views[win];
if (!view) {
view=new PluginKateKJSWrapperView();
view->win=win;
connect(win,TQT_SIGNAL(destroyed()),this,TQT_SLOT(slotWindowDestroyed()));
m_views.insert(win,view);
KJS::Interpreter *js = m_part->interpreter();
KJS::ExecState *exec = js->globalExec();
view->actionCollectionObj=m_part->factory()->createProxy(exec,view->actionCollection());
view->winObj=m_part->factory()->createProxy(exec,win);
} else kdDebug()<<"returning cached View/Window Object"<<endl;
return view;
}
void PluginKateKJSWrapper::addView(Kate::MainWindow *win)
{
PluginKateKJSWrapperView * view=getViewObject(win); // this is needed to ensure correct caching the javascript object
KJS::Interpreter *js = m_part->interpreter();
KJS::ExecState *exec = js->globalExec();
exec->clearException();
kdDebug()<<"****************************************************************************************"<<endl;
kdDebug()<<"PluginKateKJSWrapper::addView"<<endl;
kdDebug()<<"****************************************************************************************"<<endl;
kdDebug()<<"checking for newWindowHandler"<<endl;
if (!m_newWindowHandler.isNull()) {
KJS::List param;
param.append(view->winObj);
KJS::Object newWinFunc=m_newWindowHandler.toObject(exec);
if (exec->hadException()) {
exec->clearException();
} else {
if (newWinFunc.implementsCall()) {
newWinFunc.call(exec,js->globalObject(),param);
if (exec->hadException()) {
kdDebug()<<"Error while calling newWindowHandler"<<endl;
exec->clearException();
}
}
}
}
if (exec->hadException()) kdDebug()<<"void PluginKateKJSWrapper::addView(Kate::MainWindow *win): exec had an exception - 1"<<endl;
kdDebug()<<"checking for toolview constructors"<<endl;
if (! (m_toolViewConstructors.isNull() || (m_toolViewConstructors.type()==KJS::NullType))) {
KJS::Object constrs=m_toolViewConstructors.toObject(exec);
if (!exec->hadException()) {
if (TQString(constrs.classInfo()->className)=="Array") {
kdDebug()<<"Toolview constructor array detected"<<endl;
int size=constrs.get(exec,KJS::Identifier("length")).toInteger(exec);
if (exec->hadException()) {
exec->clearException();
kdDebug()<<"Error while retrieving array length"<<endl;
}
else {
for (int i=0;i<size;i++) {
KJS::Object constrO=constrs.get(exec,i).toObject(exec);
if (exec->hadException()) {
exec->clearException();
} else {
KMDI::ToolViewAccessor *w=createToolView(m_part->factory(),js,win,view->winObj,constrO);
if (w) {
view->toolviews.append(TQGuardedPtr<KMDI::ToolViewAccessor>(w));
}
exec->clearException();
}
}
}
} else {
kdDebug()<<"Single toolview constructor detected"<<endl;
if (!constrs.implementsConstruct()) {
kdWarning()<<"wrong object type"<<endl;
} else {
KMDI::ToolViewAccessor *w=createToolView(m_part->factory(),js,win,view->winObj,constrs);
if (w) {
view->toolviews.append(TQGuardedPtr<KMDI::ToolViewAccessor>(w));
}
exec->clearException();
}
}
}
} else kdDebug()<<"void PluginKateKJSWrapper::addView(Kate::MainWindow *win): no toolview constructors"<<endl;
if (exec->hadException()) kdDebug()<<"void PluginKateKJSWrapper::addView(Kate::MainWindow *win): exec had an exception - 2"<<endl;
view->setInstance (new KInstance("kate"));
view->setXMLFile(TQString("plugins/%1/%2.rc").tqarg(m_scriptname).tqarg(m_scriptname));
win->guiFactory()->addClient (view);
}
void PluginKateKJSWrapper::slotWindowDestroyed() {
m_views.remove((void*)sender());
}
void PluginKateKJSWrapper::removeView(Kate::MainWindow *win)
{
//here toolviews must not be destroyed. Only cleanup functions called the view should be removed in the slot connected to the windows destroy signal only
m_views[win]->removeFromWindow();
}
void PluginKateKJSWrapper::applyConfig( KateKJSWrapperConfigPage *p )
{
#if 0
config->writeEntry( "Command History Length", p->sb_cmdhistlen->value() );
// truncate the cmd hist if nessecary?
config->writeEntry( "Start In", p->rg_startin->id(p->rg_startin->selected()) );
config->sync();
#endif
}
KateKJSWrapperConfigPage::KateKJSWrapperConfigPage(KJS::Object pageConstructor,PluginKateKJSWrapper* parent,
TQWidget *parentWidget)
: Kate::PluginConfigPage( parentWidget ),m_plugin(parent)
{
TQVBoxLayout *l=new TQVBoxLayout(this);
l->setAutoAdd(true);
l->activate();
KJS::Interpreter *js = parent->m_part->interpreter();
KJS::ExecState *exec = js->globalExec();
exec->clearException();
KJS::List param;
param.append(parent->m_part->factory()->createProxy(exec,this,0));
m_pageObject=pageConstructor.construct(exec,param);
}
static void callJS(KJSEmbed::KJSEmbedPart *p,KJS::Object o,const TQString& funcName){
KJS::Interpreter *js = p->interpreter();
KJS::ExecState *exec = js->globalExec();
KJS::List param;
exec->clearException();
KJS::Value funcV=o.get(exec,KJS::Identifier(funcName));
if (exec->hadException()) {
#warning clear exception ?
return;
}
KJS::Object func=funcV.toObject(exec);
if (exec->hadException()) {
#warning clear exception ?
return;
}
if (func.implementsCall()) {
func.call(exec,o,param);
if (js->globalExec()->hadException()) {
#warning clear exception ?
return;
}
}
}
void KateKJSWrapperConfigPage::apply()
{
callJS(m_plugin->m_part,m_pageObject,"apply");
}
void KateKJSWrapperConfigPage::reset()
{
callJS(m_plugin->m_part,m_pageObject,"reset");
}
void KateKJSWrapperConfigPage::defaults()
{
callJS(m_plugin->m_part,m_pageObject,"defaults");
}
Kate::JS::ToolView::ToolView(KJS::Object constr, KJS::ExecState *exec, KJSEmbed::JSFactory *factory, KJS::List parameters, const char *name):TQVBox(0,name) {
parameters.append(factory->createProxy(exec,this));
handler=constr.construct(exec,parameters);
}
Kate::JS::ToolView::~ToolView() {
}