summaryrefslogtreecommitdiffstats
path: root/lib/kross/main
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kross/main')
-rw-r--r--lib/kross/main/Makefile.am33
-rw-r--r--lib/kross/main/krossconfig.cpp36
-rw-r--r--lib/kross/main/krossconfig.h116
-rw-r--r--lib/kross/main/mainmodule.cpp117
-rw-r--r--lib/kross/main/mainmodule.h181
-rw-r--r--lib/kross/main/manager.cpp248
-rw-r--r--lib/kross/main/manager.h168
-rw-r--r--lib/kross/main/scriptaction.cpp247
-rw-r--r--lib/kross/main/scriptaction.h309
-rw-r--r--lib/kross/main/scriptcontainer.cpp293
-rw-r--r--lib/kross/main/scriptcontainer.h210
-rw-r--r--lib/kross/main/scriptguiclient.cpp384
-rw-r--r--lib/kross/main/scriptguiclient.h217
-rw-r--r--lib/kross/main/wdgscriptsmanager.cpp354
-rw-r--r--lib/kross/main/wdgscriptsmanager.h60
-rw-r--r--lib/kross/main/wdgscriptsmanagerbase.ui247
16 files changed, 3220 insertions, 0 deletions
diff --git a/lib/kross/main/Makefile.am b/lib/kross/main/Makefile.am
new file mode 100644
index 00000000..0ab90117
--- /dev/null
+++ b/lib/kross/main/Makefile.am
@@ -0,0 +1,33 @@
+include $(top_srcdir)/lib/kross/Makefile.global
+
+lib_LTLIBRARIES = libkrossmain.la
+
+libkrossmain_la_SOURCES = krossconfig.cpp mainmodule.cpp scriptcontainer.cpp manager.cpp \
+ scriptaction.cpp scriptguiclient.cpp wdgscriptsmanagerbase.ui wdgscriptsmanager.cpp
+
+libkrossmain_la_LDFLAGS = $(all_libraries) $(VER_INFO) -Wnounresolved
+
+mainincludedir=$(includedir)/kross/main
+
+maininclude_HEADERS = \
+ krossconfig.h \
+ mainmodule.h \
+ manager.h \
+ scriptaction.h \
+ scriptcontainer.h \
+ scriptguiclient.h \
+ wdgscriptsmanager.h \
+ wdgscriptsmanagerbase.h
+
+libkrossmain_la_LIBADD = \
+ $(LIB_QT) \
+ $(LIB_KDECORE) \
+ $(LIB_KFILE) \
+ $(LIB_KDEUI) \
+ $(LIB_KNEWSTUFF) \
+ $(LIB_KROSS_API)
+
+METASOURCES = AUTO
+SUBDIRS = .
+INCLUDES = $(KROSS_INCLUDES) $(all_includes)
+noinst_HEADERS = wdgscriptsmanager.h
diff --git a/lib/kross/main/krossconfig.cpp b/lib/kross/main/krossconfig.cpp
new file mode 100644
index 00000000..61984532
--- /dev/null
+++ b/lib/kross/main/krossconfig.cpp
@@ -0,0 +1,36 @@
+/***************************************************************************
+ * krossconfig.h
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include "krossconfig.h"
+
+#ifdef KROSS_DEBUG_ENABLED
+
+#include <kdebug.h>
+
+void Kross::krossdebug(const QString &s)
+{
+ kdDebug() << "Kross: " << s << endl;
+}
+
+void Kross::krosswarning(const QString &s)
+{
+ kdWarning() << "Kross: " << s << endl;
+}
+
+#endif
diff --git a/lib/kross/main/krossconfig.h b/lib/kross/main/krossconfig.h
new file mode 100644
index 00000000..6b8bb25d
--- /dev/null
+++ b/lib/kross/main/krossconfig.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * krossconfig.h
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef KROSS_MAIN_KROSSCONFIG_H
+#define KROSS_MAIN_KROSSCONFIG_H
+
+#include <qstring.h>
+
+/**
+ * The Kross scripting bridge to embed scripting functionality
+ * into an application.
+ *
+ * - abstract API to access the scripting functionality.
+ * - interpreter independend to be able to decide on runtime
+ * if we like to use the python, kjs (KDE JavaScript) or
+ * whatever scripting interpreter.
+ * - flexibility by beeing able to connect different
+ * scripting interpreters together into something like
+ * a "working chain" (e.g. python-script script1 spends
+ * some functionality the kjs-script script2 likes to
+ * use.
+ * - transparently bridge functionality wrappers like
+ * \a Kross::KexiDB together with interpreters like \a Kross::Python.
+ * - Introspection where needed to be able to manipulate
+ * behaviours and functionality on runtime.
+ * - Qt/KDE based, so use the extended techs both spends.
+ * - integrate nicly as powerfull scripting system into the
+ * Kexi application.
+ *
+ * \author Sebastian Sauer
+ * \sa http://www.koffice.org/kexi
+ * \sa http://www.dipe.org/kross
+ */
+namespace Kross {
+
+ /// Debugging enabled.
+ #define KROSS_DEBUG_ENABLED
+
+ #ifdef KROSS_DEBUG_ENABLED
+
+ /**
+ * Debugging function.
+ */
+ void krossdebug(const QString &s);
+
+ /**
+ * Warning function.
+ */
+ void krosswarning(const QString &s);
+
+ #else
+ // Define these to an empty statement if debugging is disabled.
+ #define krossdebug(x)
+ #define krosswarning(x)
+ #endif
+
+ /**
+ * The common Kross API used as common codebase.
+ *
+ * The API spends \a Kross::Api::Object and more specialized
+ * classes to bridge other Kross parts together. Interaction
+ * between objects got wrapped at runtime and introspection-
+ * functionality enables dynamic manipulations.
+ * The proxy functionality prevents cross-dependencies
+ * between Kross parts like the \a Kross::Python implementation
+ * and the \a Kross::KexiDB wrapper.
+ *
+ * \author Sebastian Sauer
+ */
+ namespace Api {
+
+ //#define KROSS_API_OBJECT_CTOR_DEBUG
+ //#define KROSS_API_OBJECT_DTOR_DEBUG
+ //#define KROSS_API_OBJECT_ADDCHILD_DEBUG
+ //#define KROSS_API_OBJECT_REMCHILD_DEBUG
+ //#define KROSS_API_OBJECT_CALL_DEBUG
+
+ //#define KROSS_API_EVENT_CALL_DEBUG
+
+ //#define KROSS_API_CALLABLE_CALL_DEBUG
+ //#define KROSS_API_CALLABLE_CHECKARG_DEBUG
+
+ //#define KROSS_API_EVENTSLOT_CALL_DEBUG
+ //#define KROSS_API_EVENTSIGNAL_CALL_DEBUG
+
+ // The name of the interpreter's library. Those library got loaded
+ // dynamicly during runtime. Comment out to disable compiling of
+ // the interpreter-plugin or to hardcode the location of the lib
+ // like I did at the following line.
+
+ //#define KROSS_PYTHON_LIBRARY "/home/snoopy/cvs/kde/trunk/koffice/lib/kross/python/krosspython.la"
+ #define KROSS_PYTHON_LIBRARY "krosspython"
+ #define KROSS_RUBY_LIBRARY "krossruby"
+
+ }
+
+}
+
+#endif
+
diff --git a/lib/kross/main/mainmodule.cpp b/lib/kross/main/mainmodule.cpp
new file mode 100644
index 00000000..0630e81a
--- /dev/null
+++ b/lib/kross/main/mainmodule.cpp
@@ -0,0 +1,117 @@
+/***************************************************************************
+ * mainmodule.cpp
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include "mainmodule.h"
+
+using namespace Kross::Api;
+
+namespace Kross { namespace Api {
+
+ /// \internal
+ class MainModulePrivate
+ {
+ public:
+ /**
+ * The \a Exception this \a MainModule throwed or
+ * NULL if we don't had an exception.
+ */
+ Exception::Ptr exception;
+ };
+
+}}
+
+MainModule::MainModule(const QString& name)
+ : Module(name)
+ , d(new MainModulePrivate())
+{
+ d->exception = 0;
+}
+
+MainModule::~MainModule()
+{
+ delete d;
+}
+
+const QString MainModule::getClassName() const
+{
+ return "Kross::Api::MainModule";
+}
+
+bool MainModule::hadException()
+{
+ return d->exception != 0;
+}
+
+Exception::Ptr MainModule::getException()
+{
+ return d->exception;
+}
+
+void MainModule::setException(Exception::Ptr exception)
+{
+ d->exception = exception;
+}
+
+#if 0
+bool MainModule::hasChild(const QString& name) const
+{
+ return Callable::hasChild(name);
+}
+#endif
+
+EventSignal::Ptr MainModule::addSignal(const QString& name, QObject* sender, QCString signal)
+{
+ EventSignal* event = new EventSignal(name, sender, signal);
+ if(! addChild(name, event)) {
+ krosswarning( QString("Failed to add signal name='%1' signature='%2'").arg(name).arg(signal) );
+ return 0;
+ }
+ return event;
+}
+
+EventSlot::Ptr MainModule::addSlot(const QString& name, QObject* receiver, QCString slot)
+{
+ EventSlot* event = new EventSlot(name, receiver, slot);
+ if(! addChild(name, event)) {
+ krosswarning( QString("Failed to add slot name='%1' signature='%2'").arg(name).arg(slot) );
+ return 0;
+ }
+ return event;
+}
+
+QtObject::Ptr MainModule::addQObject(QObject* object, const QString& name)
+{
+ QtObject* qtobject = new QtObject(object, name);
+ if(! addChild(name, qtobject)) {
+ krosswarning( QString("Failed to add QObject name='%1'").arg(object->name()) );
+ return 0;
+ }
+ return qtobject;
+}
+
+EventAction::Ptr MainModule::addKAction(KAction* action, const QString& name)
+{
+ EventAction* event = new EventAction(name, action);
+ if(! addChild(name, event)) {
+ krosswarning( QString("Failed to add KAction name='%1'").arg(action->name()) );
+ return 0;
+ }
+ return event;
+}
+
diff --git a/lib/kross/main/mainmodule.h b/lib/kross/main/mainmodule.h
new file mode 100644
index 00000000..116e098d
--- /dev/null
+++ b/lib/kross/main/mainmodule.h
@@ -0,0 +1,181 @@
+/***************************************************************************
+ * mainmodule.h
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef KROSS_API_MAINMODULE_H
+#define KROSS_API_MAINMODULE_H
+
+#include "../api/object.h"
+#include "../api/variant.h"
+#include "../api/module.h"
+#include "../api/event.h"
+#include "../api/eventsignal.h"
+#include "../api/eventslot.h"
+#include "../api/qtobject.h"
+#include "../api/eventaction.h"
+
+#include <qstring.h>
+#include <qvariant.h>
+#include <qobject.h>
+
+#include <ksharedptr.h>
+#include <kaction.h>
+
+namespace Kross { namespace Api {
+
+ // Forward declarations.
+ class MainModulePrivate;
+
+ /**
+ * This class implements \a Module for the global
+ * \a Manager singleton and local \a ScriptContainer
+ * instances.
+ *
+ * The MainModule class provides base functionality
+ * for a root node in a tree of \a Kross::Api::Object
+ * instances.
+ */
+ class MainModule : public Module
+ {
+ public:
+
+ /// Shared pointer to implement reference-counting.
+ typedef KSharedPtr<MainModule> Ptr;
+
+ /**
+ * Constructor.
+ *
+ * \param name the name of the \a Module . While the
+ * global manager module has the name "Kross"
+ * the \a ScriptContainer instances are accessible
+ * by there \a ScriptContainer::getName() name.
+ */
+ explicit MainModule(const QString& name);
+
+ /**
+ * Destructor.
+ */
+ virtual ~MainModule();
+
+ /// \see Kross::Api::Object::getClassName()
+ virtual const QString getClassName() const;
+
+ /**
+ * \return true if the script throwed an exception
+ * else false.
+ */
+ bool hadException();
+
+ /**
+ * \return the \a Exception this module throwed.
+ */
+ Exception::Ptr getException();
+
+ /**
+ * Set the \a Exception this module throwed.
+ *
+ * \param exception The \a Exception this module throws or
+ * NULL if you like to clear exception and to let
+ * \a hadException() return false.
+ */
+ void setException(Exception::Ptr exception);
+
+#if 0
+ /**
+ * Returns if the defined child is avaible.
+ *
+ * \return true if child exists else false.
+ */
+ bool hasChild(const QString& name) const;
+#endif
+
+ /**
+ * Add a Qt signal to the \a Module by creating
+ * an \a EventSignal for it.
+ *
+ * \param name the name the \a EventSignal is
+ * reachable as
+ * \param sender the QObject instance which
+ * is the sender of the \p signal
+ * \param signal the Qt signal macro the \p sender
+ * emits to call the \a EventSignal
+ * \return the newly added \a EventSignal instance
+ * which is now a child of this \a MainModule
+ */
+ EventSignal::Ptr addSignal(const QString& name, QObject* sender, QCString signal);
+
+ /**
+ * Add a Qt slot to the \a Module by creating
+ * an \a EventSlot for it.
+ *
+ * \param name the name the \a EventSlot is
+ * reachable as
+ * \param receiver the QObject instance which
+ * is the receiver of the \p signal
+ * \param slot the Qt slot macro of the \p receiver
+ * to invoke if the \a EventSlot got called.
+ * \return the newly added \a EventSlot instance
+ * which is now a child of this \a MainModule
+ */
+ EventSlot::Ptr addSlot(const QString& name, QObject* receiver, QCString slot);
+
+ /**
+ * Add a \a QObject to the eventcollection. All
+ * signals and slots the QObject has will be
+ * added to a new \a EventCollection instance
+ * which is child of this \a EventCollection
+ * instance.
+ *
+ * \param object the QObject instance that should
+ * be added to this \a MainModule
+ * \param name the name under which this QObject instance
+ * should be registered as
+ * \return the newly added \a QtObject instance
+ * which is now a child of this \a MainModule
+ */
+ QtObject::Ptr addQObject(QObject* object, const QString& name = QString::null);
+
+ /**
+ * Add a \a KAction to the eventcollection. The
+ * KAction will be wrapped by a \a EventAction
+ * and will be added to this collection.
+ *
+ * \param name name to identify the \a action by
+ * \param action the KAction instance that should
+ * be added to this \a MainModule
+ * \return the newly added \a EventAction instance
+ * which is now a child of this \a MainModule
+ *
+ * \todo check \a name dox.
+ */
+ EventAction::Ptr addKAction(KAction* action, const QString& name = QString::null);
+
+ //typedef QValueList<Callable::Ptr> EventList;
+ //EventList getEvents();
+ //const QString& serializeToXML();
+ //void unserializeFromXML(const QString& xml);
+
+ private:
+ /// Private d-pointer class.
+ MainModulePrivate* d;
+ };
+
+}}
+
+#endif
+
diff --git a/lib/kross/main/manager.cpp b/lib/kross/main/manager.cpp
new file mode 100644
index 00000000..cdb4d363
--- /dev/null
+++ b/lib/kross/main/manager.cpp
@@ -0,0 +1,248 @@
+/***************************************************************************
+ * manager.cpp
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include "manager.h"
+
+#include "../api/interpreter.h"
+//#include "../api/qtobject.h"
+#include "../api/eventslot.h"
+#include "../api/eventsignal.h"
+//#include "../api/script.h"
+
+#include "krossconfig.h"
+#include "scriptcontainer.h"
+
+#include <qobject.h>
+#include <qfile.h>
+#include <qregexp.h>
+
+#include <klibloader.h>
+#include <klocale.h>
+#include <kstaticdeleter.h>
+
+extern "C"
+{
+ typedef Kross::Api::Object* (*def_module_func)(Kross::Api::Manager*);
+}
+
+using namespace Kross::Api;
+
+namespace Kross { namespace Api {
+
+ /// @internal
+ class ManagerPrivate
+ {
+ public:
+ /// List of \a InterpreterInfo instances.
+ QMap<QString, InterpreterInfo*> interpreterinfos;
+
+ /// Loaded modules.
+ QMap<QString, Module::Ptr> modules;
+ };
+
+ /**
+ * The Manager-singleton instance is NULL by default till the
+ * Manager::scriptManager() method got called first time.
+ */
+ static KSharedPtr<Manager> m_manager = KSharedPtr<Manager>(0);
+
+}}
+
+Manager* Manager::scriptManager()
+{
+ if(! m_manager.data()) {
+ // Create the Manager-singleton on demand.
+ m_manager = KSharedPtr<Manager>( new Manager() );
+ }
+
+ // and finally return the singleton.
+ return m_manager.data();
+}
+
+Manager::Manager()
+ : MainModule("Kross") // the manager has the name "Kross"
+ , d( new ManagerPrivate() )
+{
+#ifdef KROSS_PYTHON_LIBRARY
+ QString pythonlib = QFile::encodeName( KLibLoader::self()->findLibrary(KROSS_PYTHON_LIBRARY) );
+ if(! pythonlib.isEmpty()) { // If the Kross Python plugin exists we offer it as supported scripting language.
+ InterpreterInfo::Option::Map pythonoptions;
+ pythonoptions.replace("restricted",
+ new InterpreterInfo::Option("Restricted", "Restricted Python interpreter", QVariant(false,0))
+ );
+ d->interpreterinfos.replace("python",
+ new InterpreterInfo("python",
+ pythonlib, // library
+ "*.py", // file filter-wildcard
+ QStringList() << /* "text/x-python" << */ "application/x-python", // mimetypes
+ pythonoptions // options
+ )
+ );
+ }
+#endif
+#ifdef KROSS_RUBY_LIBRARY
+ QString rubylib = QFile::encodeName( KLibLoader::self()->findLibrary(KROSS_RUBY_LIBRARY) );
+ if(! rubylib.isEmpty()) { // If the Kross Ruby plugin exists we offer it as supported scripting language.
+ InterpreterInfo::Option::Map rubyoptions;
+ rubyoptions.replace("safelevel",
+ new InterpreterInfo::Option("safelevel", "Level of safety of the Ruby interpreter", QVariant(0)) // 0 -> unsafe, 4 -> very safe
+ );
+ d->interpreterinfos.replace("ruby",
+ new InterpreterInfo("ruby",
+ rubylib, // library
+ "*.rb", // file filter-wildcard
+ QStringList() << /* "text/x-ruby" << */ "application/x-ruby", // mimetypes
+ rubyoptions // options
+ )
+ );
+ } else {
+ krossdebug("Ruby interpreter for kross in unavailable");
+ }
+#endif
+}
+
+Manager::~Manager()
+{
+ for(QMap<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it)
+ delete it.data();
+ delete d;
+}
+
+QMap<QString, InterpreterInfo*> Manager::getInterpreterInfos()
+{
+ return d->interpreterinfos;
+}
+
+bool Manager::hasInterpreterInfo(const QString& interpretername) const
+{
+ return d->interpreterinfos.contains(interpretername);
+}
+
+InterpreterInfo* Manager::getInterpreterInfo(const QString& interpretername)
+{
+ return d->interpreterinfos[interpretername];
+}
+
+const QString Manager::getInterpreternameForFile(const QString& file)
+{
+ QRegExp rx;
+ rx.setWildcard(true);
+ for(QMap<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it) {
+ rx.setPattern((*it)->getWildcard());
+ if( file.find(rx) >= 0 )
+ return (*it)->getInterpretername();
+ }
+ return QString::null;
+}
+
+ScriptContainer::Ptr Manager::getScriptContainer(const QString& scriptname)
+{
+ //TODO at the moment we don't share ScriptContainer instances.
+
+ //if(d->m_scriptcontainers.contains(scriptname))
+ // return d->m_scriptcontainers[scriptname];
+ ScriptContainer* scriptcontainer = new ScriptContainer(scriptname);
+ //ScriptContainer script(this, scriptname);
+ //d->m_scriptcontainers.replace(scriptname, scriptcontainer);
+
+ return scriptcontainer;
+}
+
+Interpreter* Manager::getInterpreter(const QString& interpretername)
+{
+ setException(0); // clear previous exceptions
+
+ if(! d->interpreterinfos.contains(interpretername)) {
+ setException( new Exception(i18n("No such interpreter '%1'").arg(interpretername)) );
+ return 0;
+ }
+
+ return d->interpreterinfos[interpretername]->getInterpreter();
+}
+
+const QStringList Manager::getInterpreters()
+{
+ QStringList list;
+
+ QMap<QString, InterpreterInfo*>::Iterator it( d->interpreterinfos.begin() );
+ for(; it != d->interpreterinfos.end(); ++it)
+ list << it.key();
+
+//list << "TestCase";
+
+ return list;
+}
+
+bool Manager::addModule(Module::Ptr module)
+{
+ QString name = module->getName();
+ //if( d->modules.contains(name) ) return false;
+ d->modules.replace(name, module);
+ return true;
+}
+
+Module::Ptr Manager::loadModule(const QString& modulename)
+{
+ Module::Ptr module = 0;
+
+ if(d->modules.contains(modulename)) {
+ module = d->modules[modulename];
+ if(module)
+ return module;
+ else
+ krossdebug( QString("Manager::loadModule(%1) =======> Modulename registered, but module is invalid!").arg(modulename) );
+ }
+
+ KLibLoader* loader = KLibLoader::self();
+ KLibrary* lib = loader->globalLibrary( modulename.latin1() );
+ if(! lib) {
+ krosswarning( QString("Failed to load module '%1': %2").arg(modulename).arg(loader->lastErrorMessage()) );
+ return 0;
+ }
+ krossdebug( QString("Successfully loaded module '%1'").arg(modulename) );
+
+ def_module_func func;
+ func = (def_module_func) lib->symbol("init_module");
+
+ if(! func) {
+ krosswarning( QString("Failed to determinate init function in module '%1'").arg(modulename) );
+ return 0;
+ }
+
+ try {
+ module = (Kross::Api::Module*) (func)(this);
+ }
+ catch(Kross::Api::Exception::Ptr e) {
+ krosswarning( e->toString() );
+ module = 0;
+ }
+ lib->unload();
+
+ if(! module) {
+ krosswarning( QString("Failed to load module '%1'").arg(modulename) );
+ return 0;
+ }
+
+ // Don't remember module cause we like to have freeing it handled by the caller.
+ //d->modules.replace(modulename, module);
+
+ //krossdebug( QString("Kross::Api::Manager::loadModule modulename='%1' module='%2'").arg(modulename).arg(module->toString()) );
+ return module;
+}
+
diff --git a/lib/kross/main/manager.h b/lib/kross/main/manager.h
new file mode 100644
index 00000000..0de5833f
--- /dev/null
+++ b/lib/kross/main/manager.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+ * manager.h
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef KROSS_API_MANAGER_H
+#define KROSS_API_MANAGER_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qmap.h>
+//#include <qvariant.h>
+#include <ksharedptr.h>
+
+class QObject;
+
+#include "../api/object.h"
+#include "mainmodule.h"
+
+namespace Kross { namespace Api {
+
+ // Forward declarations.
+ class Interpreter;
+ class Object;
+ class EventSlot;
+ class EventSignal;
+ class ScriptContainer;
+ class ManagerPrivate;
+ class InterpreterInfo;
+
+ /**
+ * The Manager class is the main entry point to work with
+ * Kross. It spends an abstraction layer between what is
+ * under the hood of Kross and the functionality you need
+ * to access.
+ * Use \a Interpreter to just work with some implementated
+ * interpreter like python. While \a Script spends a more
+ * flexible container.
+ */
+ class KDE_EXPORT Manager : public MainModule
+ {
+ protected:
+
+ /**
+ * Constructor. Use \a scriptManager() to access
+ * the Manager singleton instance.
+ */
+ Manager();
+
+ public:
+
+ /**
+ * Destructor.
+ */
+ ~Manager();
+
+ /**
+ * Return the Manager instance. Always use this
+ * function to access the Manager singleton.
+ */
+ static Manager* scriptManager();
+
+ /**
+ * \return a map with \a InterpreterInfo* instances
+ * used to describe interpreters.
+ */
+ QMap<QString, InterpreterInfo*> getInterpreterInfos();
+
+ /**
+ * \return true if there exists an interpreter with the
+ * name \p interpretername else false.
+ */
+ bool hasInterpreterInfo(const QString& interpretername) const;
+
+ /**
+ * \return the \a InterpreterInfo* matching to the defined
+ * \p interpretername or NULL if there does not exists such
+ * a interpreter.
+ */
+ InterpreterInfo* getInterpreterInfo(const QString& interpretername);
+
+ /**
+ * \return the name of the \a Interpreter that feels responsible
+ * for the defined \p file .
+ *
+ * \param file The filename we should try to determinate the
+ * interpretername for.
+ * \return The name of the \a Interpreter which will be used
+ * to execute the file or QString::null if we failed
+ * to determinate a matching interpreter for the file.
+ */
+ const QString getInterpreternameForFile(const QString& file);
+
+ /**
+ * Return the existing \a ScriptContainer with scriptname
+ * or create a new \a ScriptContainer instance and associate
+ * the passed scriptname with it.
+ *
+ * \param scriptname The name of the script. This
+ * should be unique for each \a Script and
+ * could be something like the filename.
+ * \return The \a ScriptContainer instance matching to
+ * scriptname.
+ */
+ KSharedPtr<ScriptContainer> getScriptContainer(const QString& scriptname);
+
+ /**
+ * Return the \a Interpreter instance defined by
+ * the interpretername.
+ *
+ * \param interpretername The name of the interpreter.
+ * e.g. "python" or "kjs".
+ * \return The Interpreter instance or NULL if there
+ * does not exists an interpreter with such
+ * an interpretername.
+ */
+ Interpreter* getInterpreter(const QString& interpretername);
+
+ /**
+ * \return a list of names of the at the backend
+ * supported interpreters.
+ */
+ const QStringList getInterpreters();
+
+ /**
+ * Add the an external module to the global shared list of
+ * loaded modules.
+ *
+ * @param module The @a Module instace to add.
+ * @return true if the module was added successfully else
+ * false.
+ */
+ bool addModule(Module::Ptr module);
+
+ /**
+ * Load an external module and return it.
+ *
+ * \param modulename The name of the library we should try to
+ * load. Those library needs to be a valid kross module.
+ * \return The loaded \a Object or NULL if loading
+ * failed. The loaded Module isn't added to the global
+ * shared list of modules.
+ */
+ Module::Ptr loadModule(const QString& modulename);
+
+ private:
+ /// Private d-pointer class.
+ ManagerPrivate* d;
+ };
+
+}}
+
+#endif
+
diff --git a/lib/kross/main/scriptaction.cpp b/lib/kross/main/scriptaction.cpp
new file mode 100644
index 00000000..06ee9dd7
--- /dev/null
+++ b/lib/kross/main/scriptaction.cpp
@@ -0,0 +1,247 @@
+/***************************************************************************
+ * scriptaction.cpp
+ * This file is part of the KDE project
+ * copyright (C) 2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include "scriptaction.h"
+#include "manager.h"
+
+#include <qstylesheet.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <kurl.h>
+#include <kstandarddirs.h>
+#include <kmimetype.h>
+
+using namespace Kross::Api;
+
+namespace Kross { namespace Api {
+
+ /// @internal
+ class ScriptActionPrivate
+ {
+ public:
+ /**
+ * The packagepath is the directory that belongs to this
+ * \a ScriptAction instance. If this \a ScriptAction points
+ * to a scriptfile the packagepath will be the directory
+ * the scriptfile is located in.
+ */
+ QString packagepath;
+
+ /**
+ * List of logs this \a ScriptAction has. Initialization,
+ * execution and finalization should be logged for
+ * example. So, the logs are usuabled to provide some
+ * more detailed visual information to the user what
+ * our \a ScriptAction did so far.
+ */
+ QStringList logs;
+
+ /**
+ * The versionnumber this \a ScriptAction has. We are using
+ * the version to handle \a ScriptAction instances which
+ * have the same unique \a ScriptAction::name() . If the name
+ * is the same, we are able to use the version to determinate
+ * which \a ScriptAction is newer / replaces the other.
+ */
+ int version;
+
+ /**
+ * The description used to provide a way to the user to describe
+ * the \a ScriptAction with a longer string.
+ */
+ QString description;
+
+ /**
+ * List of \a ScriptActionCollection instances this \a ScriptAction
+ * is attached to.
+ */
+ QValueList<ScriptActionCollection*> collections;
+
+ /**
+ * Constructor.
+ */
+ explicit ScriptActionPrivate() : version(0) {}
+ };
+
+}}
+
+ScriptAction::ScriptAction(const QString& file)
+ : KAction(0, file.latin1())
+ , Kross::Api::ScriptContainer(file)
+ , d( new ScriptActionPrivate() ) // initialize d-pointer class
+{
+ KURL url(file);
+ if(url.isLocalFile()) {
+ setFile(file);
+ setText(url.fileName());
+ setIcon(KMimeType::iconForURL(url));
+ }
+ else {
+ setText(file);
+ }
+
+ setDescription(file);
+ setEnabled(false);
+}
+
+ScriptAction::ScriptAction(const QString& scriptconfigfile, const QDomElement& element)
+ : KAction()
+ , Kross::Api::ScriptContainer()
+ , d( new ScriptActionPrivate() ) // initialize d-pointer class
+{
+ QString name = element.attribute("name");
+ QString text = element.attribute("text");
+ QString description = element.attribute("description");
+ QString file = element.attribute("file");
+ QString icon = element.attribute("icon");
+
+ QString version = element.attribute("version");
+ bool ok;
+ int v = version.toInt(&ok);
+ if(ok) d->version = v;
+
+ if(file.isEmpty()) {
+ if(text.isEmpty())
+ text = name;
+ }
+ else {
+ if(name.isEmpty())
+ name = file;
+ if(text.isEmpty())
+ text = file;
+ }
+
+ //d->scriptcontainer = Manager::scriptManager()->getScriptContainer(name);
+
+ QString interpreter = element.attribute("interpreter");
+ if(interpreter.isNull())
+ setEnabled(false);
+ else
+ setInterpreterName( interpreter );
+
+ if(file.isNull()) {
+ setCode( element.text().stripWhiteSpace() );
+ if(description.isNull())
+ description = text;
+ ScriptContainer::setName(name);
+ }
+ else {
+ QDir dir = QFileInfo(scriptconfigfile).dir(true);
+ d->packagepath = dir.absPath();
+ QFileInfo fi(dir, file);
+ file = fi.absFilePath();
+ setEnabled(fi.exists());
+ setFile(file);
+ if(icon.isNull())
+ icon = KMimeType::iconForURL( KURL(file) );
+ if(description.isEmpty())
+ description = QString("%1<br>%2").arg(text.isEmpty() ? name : text).arg(file);
+ else
+ description += QString("<br>%1").arg(file);
+ ScriptContainer::setName(file);
+ }
+
+ KAction::setName(name.latin1());
+ KAction::setText(text);
+ setDescription(description);
+ KAction::setIcon(icon);
+
+ // connect signal
+ connect(this, SIGNAL(activated()), this, SLOT(activate()));
+}
+
+ScriptAction::~ScriptAction()
+{
+ detachAll();
+ delete d;
+}
+
+int ScriptAction::version() const
+{
+ return d->version;
+}
+
+const QString ScriptAction::getDescription() const
+{
+ return d->description;
+}
+
+void ScriptAction::setDescription(const QString& description)
+{
+ d->description = description;
+ setToolTip( description );
+ setWhatsThis( description );
+}
+
+void ScriptAction::setInterpreterName(const QString& name)
+{
+ setEnabled( Manager::scriptManager()->hasInterpreterInfo(name) );
+ Kross::Api::ScriptContainer::setInterpreterName(name);
+}
+
+const QString ScriptAction::getPackagePath() const
+{
+ return d->packagepath;
+}
+
+const QStringList& ScriptAction::getLogs() const
+{
+ return d->logs;
+}
+
+void ScriptAction::attach(ScriptActionCollection* collection)
+{
+ d->collections.append( collection );
+}
+
+void ScriptAction::detach(ScriptActionCollection* collection)
+{
+ d->collections.remove( collection );
+}
+
+void ScriptAction::detachAll()
+{
+ for(QValueList<ScriptActionCollection*>::Iterator it = d->collections.begin(); it != d->collections.end(); ++it)
+ (*it)->detach( this );
+}
+
+void ScriptAction::activate()
+{
+ emit activated(this);
+ Kross::Api::ScriptContainer::execute();
+ if( Kross::Api::ScriptContainer::hadException() ) {
+ QString errormessage = Kross::Api::ScriptContainer::getException()->getError();
+ QString tracedetails = Kross::Api::ScriptContainer::getException()->getTrace();
+ d->logs << QString("<b>%1</b><br>%2")
+ .arg( QStyleSheet::escape(errormessage) )
+ .arg( QStyleSheet::escape(tracedetails) );
+ emit failed(errormessage, tracedetails);
+ }
+ else {
+ emit success();
+ }
+}
+
+void ScriptAction::finalize()
+{
+ Kross::Api::ScriptContainer::finalize();
+}
+
+#include "scriptaction.moc"
diff --git a/lib/kross/main/scriptaction.h b/lib/kross/main/scriptaction.h
new file mode 100644
index 00000000..22bb37ec
--- /dev/null
+++ b/lib/kross/main/scriptaction.h
@@ -0,0 +1,309 @@
+/***************************************************************************
+ * scriptaction.h
+ * This file is part of the KDE project
+ * copyright (C) 2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef KROSS_API_SCRIPTACTION_H
+#define KROSS_API_SCRIPTACTION_H
+
+#include <qdom.h>
+#include <kaction.h>
+
+#include "scriptcontainer.h"
+
+namespace Kross { namespace Api {
+
+ // Forward declarations.
+ class ScriptContainer;
+ class ScriptActionCollection;
+ class ScriptActionPrivate;
+
+ /**
+ * A ScriptAction extends a KAction by providing a wrapper around
+ * a \a ScriptContainer to execute scripting code on activation.
+ */
+ class ScriptAction
+ : public KAction
+ , public Kross::Api::ScriptContainer
+ {
+ Q_OBJECT
+
+ /// The name of the interpreter used to execute the scripting code.
+ //Q_PROPERTY(QString interpretername READ getInterpreterName WRITE setInterpreterName)
+
+ /// The scripting code which should be executed.
+ //Q_PROPERTY(QString code READ getCode WRITE setCode)
+
+ /// The scriptfile which should be executed.
+ //Q_PROPERTY(QString file READ getFile WRITE setFile)
+
+ /// The description for this \a ScriptAction .
+ Q_PROPERTY(QString description READ getDescription WRITE setDescription)
+
+ public:
+
+ /// Shared pointer to implement reference-counting.
+ typedef KSharedPtr<ScriptAction> Ptr;
+
+ /// A list of \a ScriptAction instances.
+ //typedef QValueList<ScriptAction::Ptr> List;
+
+ /**
+ * Constructor.
+ *
+ * \param file The KURL scriptfile this \a ScriptAction
+ * points to.
+ */
+ explicit ScriptAction(const QString& file);
+
+ /**
+ * Constructor.
+ *
+ * \param scriptconfigfile The XML-configurationfile
+ * the DOM-element was readed from.
+ * \param element The QDomElement which will be used
+ * to setup the \a ScriptAction attributes.
+ */
+ explicit ScriptAction(const QString& scriptconfigfile, const QDomElement& element);
+
+ /**
+ * Destructor.
+ */
+ virtual ~ScriptAction();
+
+ /**
+ * \return the version this script has. Versions are used
+ * to be able to manage different versions of the same
+ * script. The version is 0 by default if not defined to
+ * something else in the rc-file.
+ */
+ int version() const;
+
+ /**
+ * \return the description for this \a ScriptAction has.
+ */
+ const QString getDescription() const;
+
+ /**
+ * Set the description \p description for this \a ScriptAction .
+ */
+ void setDescription(const QString& description);
+
+ /**
+ * Set the name of the interpreter which will be used
+ * on activation to execute the scripting code.
+ *
+ * \param name The name of the \a Interpreter . This
+ * could be e.g. "python".
+ */
+ void setInterpreterName(const QString& name);
+
+ /**
+ * \return the path of the package this \a ScriptAction
+ * belongs to or QString::null if it doesn't belong to
+ * any package.
+ */
+ const QString getPackagePath() const;
+
+ /**
+ * \return a list of all kind of logs this \a ScriptAction
+ * does remember.
+ */
+ const QStringList& getLogs() const;
+
+ /**
+ * Attach this \a ScriptAction to the \a ScriptActionCollection
+ * \p collection .
+ */
+ void attach(ScriptActionCollection* collection);
+
+ /**
+ * Detach this \a ScriptAction from the \a ScriptActionCollection
+ * \p collection .
+ */
+ void detach(ScriptActionCollection* collection);
+
+ /**
+ * Detach this \a ScriptAction from all \a ScriptActionCollection
+ * instance his \a ScriptAction is attached to.
+ */
+ void detachAll();
+
+ public slots:
+
+ /**
+ * If the \a ScriptAction got activated the \a ScriptContainer
+ * got executed. Once this slot got executed it will emit a
+ * \a success() or \a failed() signal.
+ */
+ virtual void activate();
+
+ /**
+ * This slot finalizes the \a ScriptContainer and tries to clean
+ * any still running script.
+ */
+ void finalize();
+
+ signals:
+
+ /**
+ * This signal got emitted when this action is emitted before execution.
+ */
+ void activated(const Kross::Api::ScriptAction*);
+
+ /**
+ * This signal got emitted after this \a ScriptAction got
+ * executed successfully.
+ */
+ void success();
+
+ /**
+ * This signal got emitted after the try to execute this
+ * \a ScriptAction failed. The \p errormessage contains
+ * the error message.
+ */
+ void failed(const QString& errormessage, const QString& tracedetails);
+
+ private:
+ /// Internaly used private d-pointer.
+ ScriptActionPrivate* d;
+ };
+
+ /**
+ * A collection to store \a ScriptAction shared pointers.
+ *
+ * A \a ScriptAction instance could be stored within
+ * multiple \a ScriptActionCollection instances.
+ */
+ class ScriptActionCollection
+ {
+ private:
+
+ /**
+ * The list of \a ScriptAction shared pointers.
+ */
+ QValueList<ScriptAction::Ptr> m_list;
+
+ /**
+ * A map of \a ScriptAction shared pointers used to access
+ * the actions with there name.
+ */
+ QMap<QCString, ScriptAction::Ptr> m_actions;
+
+ /**
+ * A KActionMenu which could be used to display the
+ * content of this \a ScriptActionCollection instance.
+ */
+ KActionMenu* m_actionmenu;
+
+ /**
+ * Boolean value used to represent the modified-state. Will
+ * be true if this \a ScriptActionCollection is modified
+ * aka dirty and e.g. the \a m_actionmenu needs to be
+ * updated else its false.
+ */
+ bool m_dirty;
+
+ /**
+ * Copy-constructor. The cctor is private cause instances
+ * of this class shouldn't be copied. If that changes one
+ * day, don't forgot that it's needed to copy the private
+ * member variables as well or we may end in dirty
+ * crashes :)
+ */
+ ScriptActionCollection(const ScriptActionCollection&) {}
+
+ public:
+
+ /**
+ * Constructor.
+ *
+ * \param text The text used to display some describing caption.
+ * \param ac The KActionCollection which should be used to as
+ * initial content for the KActionMenu \a m_actionmenu .
+ * \param name The internal name.
+ */
+ ScriptActionCollection(const QString& text, KActionCollection* ac, const char* name)
+ : m_actionmenu( new KActionMenu(text, ac, name) )
+ , m_dirty(true) {}
+
+
+ /**
+ * Destructor.
+ */
+ ~ScriptActionCollection() {
+ for(QValueList<ScriptAction::Ptr>::Iterator it = m_list.begin(); it != m_list.end(); ++it)
+ (*it)->detach(this);
+ }
+
+ /**
+ * \return the \a ScriptAction instance which has the name \p name
+ * or NULL if there exists no such action.
+ */
+ ScriptAction::Ptr action(const QCString& name) { return m_actions[name]; }
+
+ /**
+ * \return a list of actions.
+ */
+ QValueList<ScriptAction::Ptr> actions() { return m_list; }
+
+ /**
+ * \return the KActionMenu \a m_actionmenu .
+ */
+ KActionMenu* actionMenu() { return m_actionmenu; }
+
+ /**
+ * Attach a \a ScriptAction instance to this \a ScriptActionCollection .
+ */
+ void attach(ScriptAction::Ptr action) {
+ m_dirty = true;
+ m_actions[ action->name() ] = action;
+ m_list.append(action);
+ m_actionmenu->insert(action);
+ action->attach(this);
+ }
+
+ /**
+ * Detach a \a ScriptAction instance from this \a ScriptActionCollection .
+ */
+ void detach(ScriptAction::Ptr action) {
+ m_dirty = true;
+ m_actions.remove(action->name());
+ m_list.remove(action);
+ m_actionmenu->remove(action);
+ action->detach(this);
+ }
+
+ /**
+ * Clear this \a ScriptActionCollection . The collection
+ * will be empty and there are no actions attach any longer.
+ */
+ void clear() {
+ for(QValueList<ScriptAction::Ptr>::Iterator it = m_list.begin(); it != m_list.end(); ++it) {
+ m_actionmenu->remove(*it);
+ (*it)->detach(this);
+ }
+ m_list.clear();
+ m_actions.clear();
+ }
+
+ };
+
+}}
+
+#endif
+
diff --git a/lib/kross/main/scriptcontainer.cpp b/lib/kross/main/scriptcontainer.cpp
new file mode 100644
index 00000000..56c9bb8e
--- /dev/null
+++ b/lib/kross/main/scriptcontainer.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ * scriptcontainer.cpp
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include "scriptcontainer.h"
+#include "../api/object.h"
+#include "../api/list.h"
+#include "../api/interpreter.h"
+#include "../api/script.h"
+#include "../main/manager.h"
+#include "mainmodule.h"
+
+#include <qfile.h>
+
+#include <klocale.h>
+
+using namespace Kross::Api;
+
+namespace Kross { namespace Api {
+
+ /// @internal
+ class ScriptContainerPrivate
+ {
+ public:
+
+ /**
+ * The \a Script instance the \a ScriptContainer uses
+ * if initialized. It will be NULL as long as we
+ * didn't initialized it what will be done on
+ * demand.
+ */
+ Script* script;
+
+ /**
+ * The unique name the \a ScriptContainer is
+ * reachable as.
+ */
+ QString name;
+
+ /**
+ * The scripting code.
+ */
+ QString code;
+
+ /**
+ * The name of the interpreter. This could be
+ * something like "python" for the python
+ * binding.
+ */
+ QString interpretername;
+
+ /**
+ * The name of the scriptfile that should be
+ * executed. Those scriptfile will be readed
+ * and the content will be used to set the
+ * scripting code and, if not defined, the
+ * used interpreter.
+ */
+ QString scriptfile;
+
+ /**
+ * Map of options that overwritte the \a InterpreterInfo::Option::Map
+ * standard options.
+ */
+ QMap<QString, QVariant> options;
+
+ };
+
+}}
+
+ScriptContainer::ScriptContainer(const QString& name)
+ : MainModule(name)
+ , d( new ScriptContainerPrivate() ) // initialize d-pointer class
+{
+ //krossdebug( QString("ScriptContainer::ScriptContainer() Ctor name='%1'").arg(name) );
+
+ d->script = 0;
+ d->name = name;
+}
+
+ScriptContainer::~ScriptContainer()
+{
+ //krossdebug( QString("ScriptContainer::~ScriptContainer() Dtor name='%1'").arg(d->name) );
+
+ finalize();
+ delete d;
+}
+
+const QString ScriptContainer::getName() const
+{
+ return d->name;
+}
+
+void ScriptContainer::setName(const QString& name)
+{
+ d->name = name;
+}
+
+QString ScriptContainer::getCode() const
+{
+ return d->code;
+}
+
+void ScriptContainer::setCode(const QString& code)
+{
+ finalize();
+ d->code = code;
+}
+
+QString ScriptContainer::getInterpreterName() const
+{
+ return d->interpretername;
+}
+
+void ScriptContainer::setInterpreterName(const QString& interpretername)
+{
+ finalize();
+ d->interpretername = interpretername;
+}
+
+QString ScriptContainer::getFile() const
+{
+ return d->scriptfile;
+}
+
+void ScriptContainer::setFile(const QString& scriptfile)
+{
+ finalize();
+ d->scriptfile = scriptfile;
+}
+
+QMap<QString, QVariant>& ScriptContainer::getOptions()
+{
+ return d->options;
+}
+
+QVariant ScriptContainer::getOption(const QString name, QVariant defaultvalue, bool /*recursive*/)
+{
+ if(d->options.contains(name))
+ return d->options[name];
+ Kross::Api::InterpreterInfo* info = Kross::Api::Manager::scriptManager()->getInterpreterInfo( d->interpretername );
+ return info ? info->getOptionValue(name, defaultvalue) : defaultvalue;
+}
+
+bool ScriptContainer::setOption(const QString name, const QVariant& value)
+{
+ Kross::Api::InterpreterInfo* info = Kross::Api::Manager::scriptManager()->getInterpreterInfo( d->interpretername );
+ if(info) {
+ if(info->hasOption(name)) {
+ d->options.replace(name, value);
+ return true;
+ } else krosswarning( QString("Kross::Api::ScriptContainer::setOption(%1, %2): No such option").arg(name).arg(value.toString()) );
+ } else krosswarning( QString("Kross::Api::ScriptContainer::setOption(%1, %2): No such interpreterinfo").arg(name).arg(value.toString()) );
+ return false;
+}
+
+Object::Ptr ScriptContainer::execute()
+{
+ if(! d->script)
+ if(! initialize())
+ return 0;
+
+ if(hadException())
+ return 0;
+
+ Object::Ptr r = d->script->execute();
+ if(d->script->hadException()) {
+ setException( d->script->getException() );
+ finalize();
+ return 0;
+ }
+ return r;
+}
+
+const QStringList ScriptContainer::getFunctionNames()
+{
+ return d->script ? d->script->getFunctionNames() : QStringList(); //FIXME init before if needed?
+}
+
+Object::Ptr ScriptContainer::callFunction(const QString& functionname, List::Ptr arguments)
+{
+ if(! d->script)
+ if(! initialize())
+ return 0;
+
+ if(hadException())
+ return 0;
+
+ if(functionname.isEmpty()) {
+ setException( new Exception(i18n("No functionname defined for ScriptContainer::callFunction().")) );
+ finalize();
+ return 0;
+ }
+
+ Object::Ptr r = d->script->callFunction(functionname, arguments);
+ if(d->script->hadException()) {
+ setException( d->script->getException() );
+ finalize();
+ return 0;
+ }
+ return r;
+}
+
+QStringList ScriptContainer::getClassNames()
+{
+ return d->script ? d->script->getClassNames() : QStringList(); //FIXME init before if needed?
+}
+
+Object::Ptr ScriptContainer::classInstance(const QString& classname)
+{
+ if(! d->script)
+ if(! initialize())
+ return 0;
+
+ if(hadException())
+ return 0;
+
+ Object::Ptr r = d->script->classInstance(classname);
+ if(d->script->hadException()) {
+ setException( d->script->getException() );
+ finalize();
+ return 0;
+ }
+ return r;
+}
+
+bool ScriptContainer::initialize()
+{
+ finalize();
+
+ if(! d->scriptfile.isNull()) {
+ krossdebug( QString("Kross::Api::ScriptContainer::initialize() file=%1").arg(d->scriptfile) );
+
+ if(d->interpretername.isNull()) {
+ d->interpretername = Manager::scriptManager()->getInterpreternameForFile( d->scriptfile );
+ if(d->interpretername.isNull()) {
+ setException( new Exception(i18n("Failed to determinate interpreter for scriptfile '%1'").arg(d->scriptfile)) );
+ return false;
+ }
+ }
+
+ QFile f( d->scriptfile );
+ if(! f.open(IO_ReadOnly)) {
+ setException( new Exception(i18n("Failed to open scriptfile '%1'").arg(d->scriptfile)) );
+ return false;
+ }
+ d->code = QString( f.readAll() );
+ f.close();
+ }
+
+ Interpreter* interpreter = Manager::scriptManager()->getInterpreter(d->interpretername);
+ if(! interpreter) {
+ setException( new Exception(i18n("Unknown interpreter '%1'").arg(d->interpretername)) );
+ return false;
+ }
+
+ d->script = interpreter->createScript(this);
+ if(! d->script) {
+ setException( new Exception(i18n("Failed to create script for interpreter '%1'").arg(d->interpretername)) );
+ return false;
+ }
+ if(d->script->hadException()) {
+ setException( d->script->getException() );
+ finalize();
+ return false;
+ }
+ setException( 0 ); // clear old exception
+
+ return true;
+}
+
+void ScriptContainer::finalize()
+{
+ delete d->script;
+ d->script = 0;
+}
+
+
diff --git a/lib/kross/main/scriptcontainer.h b/lib/kross/main/scriptcontainer.h
new file mode 100644
index 00000000..a66293a2
--- /dev/null
+++ b/lib/kross/main/scriptcontainer.h
@@ -0,0 +1,210 @@
+/***************************************************************************
+ * scriptcontainer.h
+ * This file is part of the KDE project
+ * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef KROSS_API_SCRIPTCONTAINER_H
+#define KROSS_API_SCRIPTCONTAINER_H
+
+#include "mainmodule.h"
+
+#include <qstring.h>
+#include <qvariant.h>
+#include <qobject.h>
+#include <ksharedptr.h>
+
+namespace Kross { namespace Api {
+
+ // Forward declarations.
+ class Object;
+ class List;
+ class ScriptContainerPrivate;
+
+ /**
+ * The ScriptContainer class is something like a single
+ * standalone scriptfile.
+ *
+ * Once you've such a ScriptContainer instance you're
+ * able to perform actions with it like to execute
+ * scripting code. The \a Manager takes care of
+ * handling the ScriptContainer instances application
+ * width.
+ *
+ * The class \a ScriptAction provides a higher level class
+ * to work with a \a ScriptContainer instances.
+ */
+ class ScriptContainer : public MainModule
+ {
+ // We protected the constructor cause ScriptContainer
+ // instances should be created only within the
+ // Manager::getScriptContainer() method.
+ friend class Manager;
+
+ protected:
+
+ /**
+ * Constructor.
+ *
+ * The constructor is protected cause only with the
+ * \a ScriptManager it's possible to access
+ * \a ScriptContainer instances.
+ *
+ * \param name The unique name this ScriptContainer
+ * has. It's used e.g. at the \a Manager to
+ * identify the ScriptContainer.
+ */
+ explicit ScriptContainer(const QString& name = QString::null);
+
+ public:
+
+ /// Shared pointer to implement reference-counting.
+ typedef KSharedPtr<ScriptContainer> Ptr;
+
+ /**
+ * Destructor.
+ */
+ virtual ~ScriptContainer();
+
+ /**
+ * \return the unique name this ScriptContainer is
+ * reachable as.
+ */
+ const QString getName() const;
+
+ /**
+ * Set the name this ScriptContainer is reachable as.
+ */
+ void setName(const QString& name);
+
+ /**
+ * Return the scriptcode this ScriptContainer holds.
+ */
+ QString getCode() const;
+
+ /**
+ * Set the scriptcode this ScriptContainer holds.
+ */
+ void setCode(const QString& code);
+
+ /**
+ * \return the name of the interpreter used
+ * on \a execute.
+ */
+ QString getInterpreterName() const;
+
+ /**
+ * Set the name of the interpreter used
+ * on \a execute.
+ */
+ void setInterpreterName(const QString& interpretername);
+
+ /**
+ * \return the filename which will be executed
+ * on \a execute.
+ */
+ QString getFile() const;
+
+ /**
+ * Set the filename which will be executed
+ * on \a execute. The \p scriptfile needs to
+ * be a valid local file or QString::null if
+ * you don't like to use a file rather then
+ * the with \a setCode() defined scripting code.
+ */
+ void setFile(const QString& scriptfile);
+
+ /**
+ * \return a map of options this \a ScriptContainer defines.
+ * The options are returned call-by-ref, so you are able to
+ * manipulate them.
+ */
+ QMap<QString, QVariant>& getOptions();
+
+ /**
+ * \return the value of the option defined with \p name .
+ * If there doesn't exists an option with such a name,
+ * the \p defaultvalue is returned. If \p recursive is
+ * true then first the \a ScriptContainer options are
+ * seeked for the matching \p name and if not found
+ * the \a Manager options are seeked for the \p name and
+ * if not found either the \p defaultvalue is returned.
+ */
+ QVariant getOption(const QString name, QVariant defaultvalue = QVariant(), bool recursive = false);
+
+ /**
+ * Set the \a Interpreter::Option value.
+ */
+ bool setOption(const QString name, const QVariant& value);
+
+ /**
+ * Execute the script container.
+ */
+ Object::Ptr execute();
+
+ /**
+ * Return a list of functionnames the with
+ * \a setCode defined scriptcode spends.
+ */
+ const QStringList getFunctionNames();
+
+ /**
+ * Call a function in the script container.
+ *
+ * \param functionname The name of the function
+ * to call.
+ * \param arguments Optional list of arguments
+ * passed to the function.
+ * \return \a Object instance representing
+ * the functioncall returnvalue.
+ */
+ KSharedPtr<Object> callFunction(const QString& functionname, KSharedPtr<List> arguments = 0);
+
+ /**
+ * Return a list of classes.
+ */
+ QStringList getClassNames();
+
+ /**
+ * Create and return a new class instance.
+ */
+ KSharedPtr<Object> classInstance(const QString& classname);
+
+ /**
+ * Initialize the \a Script instance.
+ *
+ * Normaly it's not needed to call this function direct cause
+ * if will be internaly called if needed (e.g. on \a execute ).
+ */
+ bool initialize();
+
+ /**
+ * Finalize the \a Script instance and free's any cached or still
+ * running executions. Normaly it's not needed to call this
+ * function direct cause the \a ScriptContainer will take care
+ * of calling it if needed.
+ */
+ void finalize();
+
+ private:
+ /// Internaly used private d-pointer.
+ ScriptContainerPrivate* d;
+ };
+
+}}
+
+#endif
+
diff --git a/lib/kross/main/scriptguiclient.cpp b/lib/kross/main/scriptguiclient.cpp
new file mode 100644
index 00000000..28a89015
--- /dev/null
+++ b/lib/kross/main/scriptguiclient.cpp
@@ -0,0 +1,384 @@
+/***************************************************************************
+ * scriptguiclient.cpp
+ * This file is part of the KDE project
+ * copyright (C) 2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include "scriptguiclient.h"
+#include "manager.h"
+#include "../api/interpreter.h"
+#include "wdgscriptsmanager.h"
+
+#include <kapplication.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <ktar.h>
+#include <kstandarddirs.h>
+
+#include <kio/netaccess.h>
+
+using namespace Kross::Api;
+
+namespace Kross { namespace Api {
+
+ /// @internal
+ class ScriptGUIClientPrivate
+ {
+ public:
+ /**
+ * The \a KXMLGUIClient that is parent of the \a ScriptGUIClient
+ * instance.
+ */
+ KXMLGUIClient* guiclient;
+
+ /**
+ * The optional parent QWidget widget.
+ */
+ QWidget* parent;
+
+ /**
+ * Map of \a ScriptActionCollection instances the \a ScriptGUIClient
+ * is attached to.
+ */
+ QMap<QString, ScriptActionCollection*> collections;
+ };
+
+}}
+
+ScriptGUIClient::ScriptGUIClient(KXMLGUIClient* guiclient, QWidget* parent)
+ : QObject( parent )
+ , KXMLGUIClient( guiclient )
+ , d( new ScriptGUIClientPrivate() ) // initialize d-pointer class
+{
+ krossdebug( QString("ScriptGUIClient::ScriptGUIClient() Ctor") );
+
+ d->guiclient = guiclient;
+ d->parent = parent;
+
+ setInstance( ScriptGUIClient::instance() );
+
+ // action to execute a scriptfile.
+ new KAction(i18n("Execute Script File..."), 0, 0, this, SLOT(executeScriptFile()), actionCollection(), "executescriptfile");
+
+ // acion to show the ScriptManagerGUI dialog.
+ new KAction(i18n("Scripts Manager..."), 0, 0, this, SLOT(showScriptManager()), actionCollection(), "configurescripts");
+
+ // The predefined ScriptActionCollection's this ScriptGUIClient provides.
+ d->collections.replace("installedscripts",
+ new ScriptActionCollection(i18n("Scripts"), actionCollection(), "installedscripts") );
+ d->collections.replace("loadedscripts",
+ new ScriptActionCollection(i18n("Loaded"), actionCollection(), "loadedscripts") );
+ d->collections.replace("executedscripts",
+ new ScriptActionCollection(i18n("History"), actionCollection(), "executedscripts") );
+
+ reloadInstalledScripts();
+}
+
+ScriptGUIClient::~ScriptGUIClient()
+{
+ krossdebug( QString("ScriptGUIClient::~ScriptGUIClient() Dtor") );
+ for(QMap<QString, ScriptActionCollection*>::Iterator it = d->collections.begin(); it != d->collections.end(); ++it)
+ delete it.data();
+ delete d;
+}
+
+bool ScriptGUIClient::hasActionCollection(const QString& name)
+{
+ return d->collections.contains(name);
+}
+
+ScriptActionCollection* ScriptGUIClient::getActionCollection(const QString& name)
+{
+ return d->collections[name];
+}
+
+QMap<QString, ScriptActionCollection*> ScriptGUIClient::getActionCollections()
+{
+ return d->collections;
+}
+
+void ScriptGUIClient::addActionCollection(const QString& name, ScriptActionCollection* collection)
+{
+ removeActionCollection(name);
+ d->collections.replace(name, collection);
+}
+
+bool ScriptGUIClient::removeActionCollection(const QString& name)
+{
+ if(d->collections.contains(name)) {
+ ScriptActionCollection* c = d->collections[name];
+ d->collections.remove(name);
+ delete c;
+ return true;
+ }
+ return false;
+}
+
+void ScriptGUIClient::reloadInstalledScripts()
+{
+ ScriptActionCollection* installedcollection = d->collections["installedscripts"];
+ if(installedcollection)
+ installedcollection->clear();
+
+ QCString partname = d->guiclient->instance()->instanceName();
+ QStringList files = KGlobal::dirs()->findAllResources("data", partname + "/scripts/*/*.rc");
+ //files.sort();
+ for(QStringList::iterator it = files.begin(); it != files.end(); ++it)
+ loadScriptConfigFile(*it);
+}
+
+bool ScriptGUIClient::installScriptPackage(const QString& scriptpackagefile)
+{
+ krossdebug( QString("Install script package: %1").arg(scriptpackagefile) );
+ KTar archive( scriptpackagefile );
+ if(! archive.open(IO_ReadOnly)) {
+ KMessageBox::sorry(0, i18n("Could not read the package \"%1\".").arg(scriptpackagefile));
+ return false;
+ }
+
+ QCString partname = d->guiclient->instance()->instanceName();
+ QString destination = KGlobal::dirs()->saveLocation("data", partname + "/scripts/", true);
+ //QString destination = KGlobal::dirs()->saveLocation("appdata", "scripts", true);
+ if(destination.isNull()) {
+ krosswarning("ScriptGUIClient::installScriptPackage() Failed to determinate location where the scriptpackage should be installed to!");
+ return false;
+ }
+
+ QString packagename = QFileInfo(scriptpackagefile).baseName();
+ destination += packagename; // add the packagename to the name of the destination-directory.
+
+ if( QDir(destination).exists() ) {
+ if( KMessageBox::warningContinueCancel(0,
+ i18n("A script package with the name \"%1\" already exists. Replace this package?" ).arg(packagename),
+ i18n("Replace")) != KMessageBox::Continue )
+ return false;
+
+ if(! KIO::NetAccess::del(destination, 0) ) {
+ KMessageBox::sorry(0, i18n("Could not uninstall this script package. You may not have sufficient permissions to delete the folder \"%1\".").arg(destination));
+ return false;
+ }
+ }
+
+ krossdebug( QString("Copy script-package to destination directory: %1").arg(destination) );
+ const KArchiveDirectory* archivedir = archive.directory();
+ archivedir->copyTo(destination, true);
+
+ reloadInstalledScripts();
+ return true;
+}
+
+bool ScriptGUIClient::uninstallScriptPackage(const QString& scriptpackagepath)
+{
+ if(! KIO::NetAccess::del(scriptpackagepath, 0) ) {
+ KMessageBox::sorry(0, i18n("Could not uninstall this script package. You may not have sufficient permissions to delete the folder \"%1\".").arg(scriptpackagepath));
+ return false;
+ }
+ reloadInstalledScripts();
+ return true;
+}
+
+bool ScriptGUIClient::loadScriptConfigFile(const QString& scriptconfigfile)
+{
+ krossdebug( QString("ScriptGUIClient::loadScriptConfig file=%1").arg(scriptconfigfile) );
+
+ QDomDocument domdoc;
+ QFile file(scriptconfigfile);
+ if(! file.open(IO_ReadOnly)) {
+ krosswarning( QString("ScriptGUIClient::loadScriptConfig(): Failed to read scriptconfigfile: %1").arg(scriptconfigfile) );
+ return false;
+ }
+ bool ok = domdoc.setContent(&file);
+ file.close();
+ if(! ok) {
+ krosswarning( QString("ScriptGUIClient::loadScriptConfig(): Failed to parse scriptconfigfile: %1").arg(scriptconfigfile) );
+ return false;
+ }
+
+ return loadScriptConfigDocument(scriptconfigfile, domdoc);
+}
+
+bool ScriptGUIClient::loadScriptConfigDocument(const QString& scriptconfigfile, const QDomDocument &document)
+{
+ ScriptActionCollection* installedcollection = d->collections["installedscripts"];
+ QDomNodeList nodelist = document.elementsByTagName("ScriptAction");
+ uint nodelistcount = nodelist.count();
+ for(uint i = 0; i < nodelistcount; i++) {
+ ScriptAction::Ptr action = new ScriptAction(scriptconfigfile, nodelist.item(i).toElement());
+
+ if(installedcollection) {
+ ScriptAction::Ptr otheraction = installedcollection->action( action->name() );
+ if(otheraction) {
+ // There exists already an action with the same name. Use the versionnumber
+ // to see if one of them is newer and if that's the case display only
+ // the newer aka those with the highest version.
+ if(action->version() < otheraction->version() && action->version() >= 0) {
+ // Just don't do anything with the above created action. The
+ // shared pointer will take care of freeing the instance.
+ continue;
+ }
+ else if(action->version() > otheraction->version() && otheraction->version() >= 0) {
+ // The previously added scriptaction isn't up-to-date any
+ // longer. Remove it from the list of installed scripts.
+ otheraction->finalize();
+ installedcollection->detach(otheraction);
+ //otheraction->detachAll() //FIXME: why it crashes with detachAll() ?
+ }
+ else {
+ // else just print a warning and fall through (so, install the action
+ // and don't care any longer of the duplicated name)...
+ krosswarning( QString("Kross::Api::ScriptGUIClient::loadScriptConfigDocument: There exists already a scriptaction with name \"%1\". Added anyway...").arg(action->name()) );
+ }
+ }
+ installedcollection->attach( action );
+ }
+
+ connect(action.data(), SIGNAL( failed(const QString&, const QString&) ),
+ this, SLOT( executionFailed(const QString&, const QString&) ));
+ connect(action.data(), SIGNAL( success() ),
+ this, SLOT( successfullyExecuted() ));
+ connect(action.data(), SIGNAL( activated(const Kross::Api::ScriptAction*) ), SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
+ }
+ emit collectionChanged(installedcollection);
+ return true;
+}
+
+void ScriptGUIClient::setXMLFile(const QString& file, bool merge, bool setXMLDoc)
+{
+ KXMLGUIClient::setXMLFile(file, merge, setXMLDoc);
+}
+
+void ScriptGUIClient::setDOMDocument(const QDomDocument &document, bool merge)
+{
+ ScriptActionCollection* installedcollection = d->collections["installedscripts"];
+ if(! merge && installedcollection)
+ installedcollection->clear();
+
+ KXMLGUIClient::setDOMDocument(document, merge);
+ loadScriptConfigDocument(xmlFile(), document);
+}
+
+void ScriptGUIClient::successfullyExecuted()
+{
+ const ScriptAction* action = dynamic_cast< const ScriptAction* >( QObject::sender() );
+ if(action) {
+ emit executionFinished(action);
+ ScriptActionCollection* executedcollection = d->collections["executedscripts"];
+ if(executedcollection) {
+ ScriptAction* actionptr = const_cast< ScriptAction* >( action );
+ executedcollection->detach(actionptr);
+ executedcollection->attach(actionptr);
+ emit collectionChanged(executedcollection);
+ }
+ }
+}
+
+void ScriptGUIClient::executionFailed(const QString& errormessage, const QString& tracedetails)
+{
+ const ScriptAction* action = dynamic_cast< const ScriptAction* >( QObject::sender() );
+ if(action)
+ emit executionFinished(action);
+ if(tracedetails.isEmpty())
+ KMessageBox::error(0, errormessage);
+ else
+ KMessageBox::detailedError(0, errormessage, tracedetails);
+}
+
+KURL ScriptGUIClient::openScriptFile(const QString& caption)
+{
+ QStringList mimetypes;
+ QMap<QString, InterpreterInfo*> infos = Manager::scriptManager()->getInterpreterInfos();
+ for(QMap<QString, InterpreterInfo*>::Iterator it = infos.begin(); it != infos.end(); ++it)
+ mimetypes.append( it.data()->getMimeTypes().join(" ").stripWhiteSpace() );
+
+ KFileDialog* filedialog = new KFileDialog(
+ QString::null, // startdir
+ mimetypes.join(" "), // filter
+ 0, // parent widget
+ "ScriptGUIClientFileDialog", // name
+ true // modal
+ );
+ if(! caption.isNull())
+ filedialog->setCaption(caption);
+ if( filedialog->exec() )
+ return filedialog->selectedURL();
+ return KURL();
+}
+
+bool ScriptGUIClient::loadScriptFile()
+{
+ KURL url = openScriptFile( i18n("Load Script File") );
+ if(url.isValid()) {
+ ScriptActionCollection* loadedcollection = d->collections["loadedscripts"];
+ if(loadedcollection) {
+ ScriptAction::Ptr action = new ScriptAction( url.path() );
+ connect(action.data(), SIGNAL( failed(const QString&, const QString&) ),
+ this, SLOT( executionFailed(const QString&, const QString&) ));
+ connect(action.data(), SIGNAL( success() ),
+ this, SLOT( successfullyExecuted() ));
+ connect(action.data(), SIGNAL( activated(const Kross::Api::ScriptAction*) ), SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
+
+ loadedcollection->detach(action);
+ loadedcollection->attach(action);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ScriptGUIClient::executeScriptFile()
+{
+ KURL url = openScriptFile( i18n("Execute Script File") );
+ if(url.isValid())
+ return executeScriptFile( url.path() );
+ return false;
+}
+
+bool ScriptGUIClient::executeScriptFile(const QString& file)
+{
+ krossdebug( QString("Kross::Api::ScriptGUIClient::executeScriptFile() file='%1'").arg(file) );
+
+ ScriptAction::Ptr action = new ScriptAction(file);
+ return executeScriptAction(action);
+}
+
+bool ScriptGUIClient::executeScriptAction(ScriptAction::Ptr action)
+{
+ connect(action.data(), SIGNAL( failed(const QString&, const QString&) ),
+ this, SLOT( executionFailed(const QString&, const QString&) ));
+ connect(action.data(), SIGNAL( success() ),
+ this, SLOT( successfullyExecuted() ));
+ connect(action.data(), SIGNAL( activated(const Kross::Api::ScriptAction*) ), SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
+ action->activate();
+ bool ok = action->hadException();
+ action->finalize(); // execution is done.
+ return ok;
+}
+
+void ScriptGUIClient::showScriptManager()
+{
+ KDialogBase* dialog = new KDialogBase(d->parent, "", true, i18n("Scripts Manager"), KDialogBase::Close);
+ WdgScriptsManager* wsm = new WdgScriptsManager(this, dialog);
+ dialog->setMainWidget(wsm);
+ dialog->resize( QSize(360, 320).expandedTo(dialog->minimumSizeHint()) );
+ dialog->show();
+}
+
+#include "scriptguiclient.moc"
diff --git a/lib/kross/main/scriptguiclient.h b/lib/kross/main/scriptguiclient.h
new file mode 100644
index 00000000..955b55d9
--- /dev/null
+++ b/lib/kross/main/scriptguiclient.h
@@ -0,0 +1,217 @@
+/***************************************************************************
+ * scriptguiclient.h
+ * This file is part of the KDE project
+ * copyright (C) 2005 by Sebastian Sauer (mail@dipe.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 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
+ * Library General Public License for more details.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#ifndef KROSS_API_SCRIPTGUICLIENT_H
+#define KROSS_API_SCRIPTGUICLIENT_H
+
+#include "scriptcontainer.h"
+#include "scriptaction.h"
+
+#include <qobject.h>
+#include <qdom.h>
+#include <kurl.h>
+#include <kxmlguiclient.h>
+
+class QWdiget;
+
+namespace Kross { namespace Api {
+
+ // Forward declarations.
+ class ScriptAction;
+ class ScriptGUIClientPrivate;
+
+ /**
+ * The ScriptGUIClient class provides abstract access to
+ * scripting code used to extend an applications functionality.
+ */
+ class KDE_EXPORT ScriptGUIClient
+ : public QObject
+ , public KXMLGUIClient
+ {
+ Q_OBJECT
+ //Q_PROPERTY(QString configfile READ getConfigFile WRITE setConfigFile)
+
+ public:
+
+ /// List of KAction instances.
+ typedef QPtrList<KAction> List;
+
+ /**
+ * Constructor.
+ *
+ * \param guiclient The KXMLGUIClient this \a ScriptGUIClient
+ * is a child of.
+ * \param parent The parent QWidget. If defined Qt will handle
+ * freeing this \a ScriptGUIClient instance else the
+ * caller has to take care of freeing this instance
+ * if not needed any longer.
+ */
+ explicit ScriptGUIClient(KXMLGUIClient* guiclient, QWidget* parent = 0);
+
+ /**
+ * Destructor.
+ */
+ virtual ~ScriptGUIClient();
+
+ /**
+ * \return true if this \a ScriptGUIClient has a \a ScriptActionCollection
+ * with the name \p name else false is returned.
+ */
+ bool hasActionCollection(const QString& name);
+
+ /**
+ * \return the \a ScriptActionCollection which has the name \p name
+ * or NULL if there exists no such \a ScriptActionCollection .
+ */
+ ScriptActionCollection* getActionCollection(const QString& name);
+
+ /**
+ * \return a map of all avaiable \a ScriptActionCollection instances
+ * this \a ScriptGUIClient knows about.
+ * Per default there are 2 collections avaiable;
+ * 1. "installedscripts" The installed collection of scripts.
+ * 2. "loadedscripts" The loaded scripts.
+ */
+ QMap<QString, ScriptActionCollection*> getActionCollections();
+
+ /**
+ * Add a new \a ScriptActionCollection with the name \p name to
+ * our map of actioncollections.
+ */
+ void addActionCollection(const QString& name, ScriptActionCollection* collection);
+
+ /**
+ * Remove the \a ScriptActionCollection defined with name \p name.
+ */
+ bool removeActionCollection(const QString& name);
+
+ /**
+ * Reload the list of installed scripts.
+ */
+ void reloadInstalledScripts();
+
+ /**
+ * Install the packagefile \p scriptpackagefile . Those
+ * packagefile should be a tar.gz-archive which will be
+ * extracted and to the users script-directory.
+ */
+ bool installScriptPackage(const QString& scriptpackagefile);
+
+ /**
+ * Uninstall the scriptpackage located in the path
+ * \p scriptpackagepath . This just deletes the whole
+ * directory.
+ */
+ bool uninstallScriptPackage(const QString& scriptpackagepath);
+
+ /**
+ * Load the scriptpackage's configurationfile
+ * \p scriptconfigfile and add the defined \a ScriptAction
+ * instances to the list of installed scripts.
+ */
+ bool loadScriptConfigFile(const QString& scriptconfigfile);
+
+ /**
+ * Load the \p document DOM-document from the scriptpackage's
+ * XML-configfile \p scriptconfigfile and add the defined
+ * \a ScriptAction instances to the list of installed scripts.
+ */
+ bool loadScriptConfigDocument(const QString& scriptconfigfile, const QDomDocument &document);
+
+ /// KXMLGUIClient overloaded method to set the XML file.
+ virtual void setXMLFile(const QString& file, bool merge = false, bool setXMLDoc = true);
+ /// KXMLGUIClient overloaded method to set the XML DOM-document.
+ virtual void setDOMDocument(const QDomDocument &document, bool merge = false);
+
+ public slots:
+
+ /**
+ * A KFileDialog will be displayed to let the user choose
+ * a scriptfile. The choosen file will be returned as KURL.
+ */
+ KURL openScriptFile(const QString& caption = QString::null);
+
+ /**
+ * A KFileDialog will be displayed to let the user choose
+ * a scriptfile that should be loaded.
+ * Those loaded \a ScriptAction will be added to the
+ * \a ScriptActionCollection of loaded scripts.
+ */
+ bool loadScriptFile();
+
+ /**
+ * A KFileDialog will be displayed to let the user choose
+ * the scriptfile that should be executed.
+ * The executed \a ScriptAction will be added to the
+ * \a ScriptActionCollection of executed scripts.
+ */
+ bool executeScriptFile();
+
+ /**
+ * Execute the scriptfile \p file . Internaly we try to use
+ * the defined filename to auto-detect the \a Interpreter which
+ * should be used for the execution.
+ */
+ bool executeScriptFile(const QString& file);
+
+ /**
+ * This method executes the \a ScriptAction \p action .
+ * Internaly we just call \a ScriptAction::activate and
+ * redirect the success/failed signals to our internal slots.
+ */
+ bool executeScriptAction(ScriptAction::Ptr action);
+
+ /**
+ * The \a ScriptManagerGUI dialog will be displayed to
+ * let the user manage the scriptfiles.
+ */
+ void showScriptManager();
+
+ private slots:
+
+ /**
+ * Called if execution of this \a ScriptAction failed and
+ * displays an errormessage-dialog.
+ */
+ void executionFailed(const QString& errormessage, const QString& tracedetails);
+
+ /**
+ * Called if execution of this \a ScriptAction was
+ * successfully. The \a ScriptAction will be added
+ * to the history-collection of successfully executed
+ * \a ScriptAction instances.
+ */
+ void successfullyExecuted();
+
+ signals:
+ /// Emitted if a \a ScriptActionCollection instances changed.
+ void collectionChanged(ScriptActionCollection*);
+ /// This signal is emited when the execution of a script is started
+ void executionStarted(const Kross::Api::ScriptAction* );
+ /// This signal is emited when the execution of a script is finished
+ void executionFinished(const Kross::Api::ScriptAction* );
+ private:
+ /// Internaly used private d-pointer.
+ ScriptGUIClientPrivate* d;
+ };
+
+}}
+
+#endif
+
diff --git a/lib/kross/main/wdgscriptsmanager.cpp b/lib/kross/main/wdgscriptsmanager.cpp
new file mode 100644
index 00000000..10924519
--- /dev/null
+++ b/lib/kross/main/wdgscriptsmanager.cpp
@@ -0,0 +1,354 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "wdgscriptsmanager.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qheader.h>
+#include <qobjectlist.h>
+#include <qtooltip.h>
+
+#include <kapplication.h>
+#include <kdeversion.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <ktoolbar.h>
+
+#if KDE_IS_VERSION(3, 4, 0)
+ // The KNewStuffSecure we use internaly for the GetHotNewStuff-functionality
+ // was introduced with KDE 3.4.
+ #define KROSS_SUPPORT_NEWSTUFF
+#endif
+
+#ifdef KROSS_SUPPORT_NEWSTUFF
+ #include <knewstuff/provider.h>
+ #include <knewstuff/engine.h>
+ #include <knewstuff/downloaddialog.h>
+ #include <knewstuff/knewstuffsecure.h>
+#endif
+
+#include "scriptguiclient.h"
+#include "scriptaction.h"
+
+namespace Kross { namespace Api {
+
+#ifdef KROSS_SUPPORT_NEWSTUFF
+class ScriptNewStuff : public KNewStuffSecure
+{
+ public:
+ ScriptNewStuff(ScriptGUIClient* scripguiclient, const QString& type, QWidget *parentWidget = 0)
+ : KNewStuffSecure(type, parentWidget)
+ , m_scripguiclient(scripguiclient) {}
+ virtual ~ScriptNewStuff() {}
+ private:
+ ScriptGUIClient* m_scripguiclient;
+ virtual void installResource() { m_scripguiclient->installScriptPackage( m_tarName ); }
+};
+#endif
+
+class ListItem : public QListViewItem
+{
+ private:
+ ScriptActionCollection* m_collection;
+ ScriptAction::Ptr m_action;
+ public:
+ ListItem(QListView* parentview, ScriptActionCollection* collection)
+ : QListViewItem(parentview), m_collection(collection), m_action(0) {}
+
+ ListItem(ListItem* parentitem, QListViewItem* afteritem, ScriptAction::Ptr action)
+ : QListViewItem(parentitem, afteritem), m_collection( parentitem->collection() ), m_action(action) {}
+
+ ScriptAction::Ptr action() const { return m_action; }
+ ScriptActionCollection* collection() const { return m_collection; }
+ //ScriptActionMenu* actionMenu() const { return m_menu; }
+};
+
+class ToolTip : public QToolTip
+{
+ public:
+ ToolTip(KListView* parent) : QToolTip(parent->viewport()), m_parent(parent) {}
+ virtual ~ToolTip () { remove(m_parent->viewport()); }
+ protected:
+ virtual void maybeTip(const QPoint& p) {
+ ListItem* item = dynamic_cast<ListItem*>( m_parent->itemAt(p) );
+ if(item) {
+ QRect r( m_parent->itemRect(item) );
+ if(r.isValid() && item->action()) {
+ tip(r, QString("<qt>%1</qt>").arg(item->action()->toolTip()));
+ }
+ }
+ }
+ private:
+ KListView* m_parent;
+};
+
+class WdgScriptsManagerPrivate
+{
+ friend class WdgScriptsManager;
+ ScriptGUIClient* m_scripguiclient;
+ ToolTip* m_tooltip;
+#ifdef KROSS_SUPPORT_NEWSTUFF
+ ScriptNewStuff* newstuff;
+#endif
+ //enum { LoadBtn = 0, UnloadBtn, InstallBtn, UninstallBtn, ExecBtn, NewStuffBtn };
+};
+
+WdgScriptsManager::WdgScriptsManager(ScriptGUIClient* scr, QWidget* parent, const char* name, WFlags fl )
+ : WdgScriptsManagerBase(parent, name, fl)
+ , d(new WdgScriptsManagerPrivate)
+{
+ d->m_scripguiclient = scr;
+ d->m_tooltip = new ToolTip(scriptsList);
+#ifdef KROSS_SUPPORT_NEWSTUFF
+ d->newstuff = 0;
+#endif
+
+ scriptsList->header()->hide();
+ //scriptsList->header()->setClickEnabled(false);
+ scriptsList->setAllColumnsShowFocus(true);
+ //scriptsList->setRootIsDecorated(true);
+ scriptsList->setSorting(-1);
+ scriptsList->addColumn("text");
+ //scriptsList->setColumnWidthMode(1, QListView::Manual);
+
+ slotFillScriptsList();
+
+ slotSelectionChanged(0);
+ connect(scriptsList, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotSelectionChanged(QListViewItem*)));
+
+ btnExec->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "exec", KIcon::MainToolbar, 16 ));
+ connect(btnExec, SIGNAL(clicked()), this, SLOT(slotExecuteScript()));
+ btnLoad->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "fileopen", KIcon::MainToolbar, 16 ));
+ connect(btnLoad, SIGNAL(clicked()), this, SLOT(slotLoadScript()));
+ btnUnload->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "fileclose", KIcon::MainToolbar, 16 ));
+ connect(btnUnload, SIGNAL(clicked()), this, SLOT(slotUnloadScript()));
+ btnInstall->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "fileimport", KIcon::MainToolbar, 16 ));
+ connect(btnInstall, SIGNAL(clicked()), this, SLOT(slotInstallScript()));
+ btnUninstall->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "fileclose", KIcon::MainToolbar, 16 ));
+ connect(btnUninstall, SIGNAL(clicked()), this, SLOT(slotUninstallScript()));
+#ifdef KROSS_SUPPORT_NEWSTUFF
+ btnNewStuff->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "knewstuff", KIcon::MainToolbar, 16 ));
+ connect(btnNewStuff, SIGNAL(clicked()), this, SLOT(slotGetNewScript()));
+#endif
+/*
+ toolBar->setIconText( KToolBar::IconTextRight );
+
+ toolBar->insertButton("exec", WdgScriptsManagerPrivate::ExecBtn, false, i18n("Execute"));
+ toolBar->addConnection(WdgScriptsManagerPrivate::ExecBtn, SIGNAL(clicked()), this, SLOT(slotExecuteScript()));
+ toolBar->insertLineSeparator();
+ toolBar->insertButton("fileopen", WdgScriptsManagerPrivate::LoadBtn, true, i18n("Load"));
+ toolBar->addConnection(WdgScriptsManagerPrivate::LoadBtn, SIGNAL(clicked()), this, SLOT(slotLoadScript()));
+ toolBar->insertButton("fileclose", WdgScriptsManagerPrivate::UnloadBtn, false, i18n("Unload"));
+ toolBar->addConnection(WdgScriptsManagerPrivate::UnloadBtn, SIGNAL(clicked()), this, SLOT(slotUnloadScript()));
+ toolBar->insertLineSeparator();
+ toolBar->insertButton("fileimport", WdgScriptsManagerPrivate::InstallBtn, true, i18n("Install"));
+ toolBar->addConnection(WdgScriptsManagerPrivate::InstallBtn, SIGNAL(clicked()), this, SLOT(slotInstallScript()));
+ toolBar->insertButton("fileclose", WdgScriptsManagerPrivate::UninstallBtn, false, i18n("Uninstall"));
+ toolBar->addConnection(WdgScriptsManagerPrivate::UninstallBtn, SIGNAL(clicked()), this, SLOT(slotUninstallScript()));
+#ifdef KROSS_SUPPORT_NEWSTUFF
+ toolBar->insertLineSeparator();
+ toolBar->insertButton("knewstuff", WdgScriptsManagerPrivate::NewStuffBtn, true, i18n("Get More Scripts"));
+ toolBar->addConnection(WdgScriptsManagerPrivate::NewStuffBtn, SIGNAL(clicked()), this, SLOT(slotGetNewScript()));
+#endif
+*/
+ connect(scr, SIGNAL( collectionChanged(ScriptActionCollection*) ),
+ this, SLOT( slotFillScriptsList() ));
+}
+
+WdgScriptsManager::~WdgScriptsManager()
+{
+ delete d->m_tooltip;
+ delete d;
+}
+
+void WdgScriptsManager::slotFillScriptsList()
+{
+ scriptsList->clear();
+
+ addItem( d->m_scripguiclient->getActionCollection("executedscripts") );
+ addItem( d->m_scripguiclient->getActionCollection("loadedscripts") );
+ addItem( d->m_scripguiclient->getActionCollection("installedscripts") );
+}
+
+void WdgScriptsManager::addItem(ScriptActionCollection* collection)
+{
+ if(! collection)
+ return;
+
+ ListItem* i = new ListItem(scriptsList, collection);
+ i->setText(0, collection->actionMenu()->text());
+ i->setOpen(true);
+
+ QValueList<ScriptAction::Ptr> list = collection->actions();
+ QListViewItem* lastitem = 0;
+ for(QValueList<ScriptAction::Ptr>::Iterator it = list.begin(); it != list.end(); ++it)
+ lastitem = addItem(*it, i, lastitem);
+}
+
+QListViewItem* WdgScriptsManager::addItem(ScriptAction::Ptr action, QListViewItem* parentitem, QListViewItem* afteritem)
+{
+ if(! action)
+ return 0;
+
+ ListItem* i = new ListItem(dynamic_cast<ListItem*>(parentitem), afteritem, action);
+ i->setText(0, action->text()); // FIXME: i18nise it for ko2.0
+ //i->setText(1, action->getDescription()); // FIXME: i18nise it for ko2.0
+ //i->setText(2, action->name());
+
+ QPixmap pm;
+ if(action->hasIcon()) {
+ KIconLoader* icons = KGlobal::iconLoader();
+ pm = icons->loadIconSet(action->icon(), KIcon::Small).pixmap(QIconSet::Small, QIconSet::Active);
+ }
+ else {
+ pm = action->iconSet(KIcon::Small, 16).pixmap(QIconSet::Small, QIconSet::Active);
+ }
+ if(! pm.isNull())
+ i->setPixmap(0, pm); // display the icon
+
+ return i;
+}
+
+void WdgScriptsManager::slotSelectionChanged(QListViewItem* item)
+{
+ ListItem* i = dynamic_cast<ListItem*>(item);
+ Kross::Api::ScriptActionCollection* installedcollection = d->m_scripguiclient->getActionCollection("installedscripts");
+
+ //toolBar->setItemEnabled(WdgScriptsManagerPrivate::ExecBtn, i && i->action());
+ //toolBar->setItemEnabled(WdgScriptsManagerPrivate::UninstallBtn, i && i->action() && i->collection() == installedcollection);
+ //toolBar->setItemEnabled(WdgScriptsManagerPrivate::UnloadBtn, i && i->action() && i->collection() != installedcollection);
+ btnExec->setEnabled(i && i->action());
+ btnUnload->setEnabled(i && i->action() && i->collection() != installedcollection);
+ btnUninstall->setEnabled(i && i->action() && i->collection() == installedcollection);
+}
+
+void WdgScriptsManager::slotLoadScript()
+{
+ if(d->m_scripguiclient->loadScriptFile())
+ slotFillScriptsList();
+}
+
+void WdgScriptsManager::slotInstallScript()
+{
+ KFileDialog* filedialog = new KFileDialog(
+ QString::null, // startdir
+ "*.tar.gz *.tgz *.bz2", // filter
+ this, // parent widget
+ "WdgScriptsManagerInstallFileDialog", // name
+ true // modal
+ );
+ filedialog->setCaption( i18n("Install Script Package") );
+
+ if(! filedialog->exec())
+ return;
+
+ if(! d->m_scripguiclient->installScriptPackage( filedialog->selectedURL().path() )) {
+ krosswarning("Failed to install scriptpackage");
+ return;
+ }
+
+ slotFillScriptsList();
+}
+
+void WdgScriptsManager::slotUninstallScript()
+{
+ ListItem* item = dynamic_cast<ListItem*>( scriptsList->currentItem() );
+ if( !item || !item->action() )
+ return;
+
+ Kross::Api::ScriptActionCollection* installedcollection = d->m_scripguiclient->getActionCollection("installedscripts");
+ if( !item->collection() || item->collection() != installedcollection)
+ return;
+
+ const QString packagepath = item->action()->getPackagePath();
+ if( !packagepath)
+ return;
+
+ if( KMessageBox::warningContinueCancel(0,
+ i18n("Uninstall the script package \"%1\" and delete the package's folder \"%2\"?")
+ .arg(item->action()->text()).arg(packagepath),
+ i18n("Uninstall")) != KMessageBox::Continue )
+ {
+ return;
+ }
+
+ if(! d->m_scripguiclient->uninstallScriptPackage(packagepath)) {
+ krosswarning("Failed to uninstall scriptpackage");
+ return;
+ }
+
+ slotFillScriptsList();
+}
+
+void WdgScriptsManager::slotExecuteScript()
+{
+ ListItem* item = dynamic_cast<ListItem*>( scriptsList->currentItem() );
+ if(item && item->action())
+ item->action()->activate();
+}
+
+void WdgScriptsManager::slotUnloadScript()
+{
+ ListItem* item = dynamic_cast<ListItem*>( scriptsList->currentItem() );
+ if(item && item->action()) {
+ item->collection()->detach( item->action() );
+ slotFillScriptsList();
+ }
+}
+
+void WdgScriptsManager::slotGetNewScript()
+{
+#ifdef KROSS_SUPPORT_NEWSTUFF
+ const QString appname = KApplication::kApplication()->name();
+ const QString type = QString("%1/script").arg(appname);
+
+ if(! d->newstuff) {
+ d->newstuff = new ScriptNewStuff(d->m_scripguiclient, type);
+ connect(d->newstuff, SIGNAL(installFinished()), this, SLOT(slotResourceInstalled()));
+ }
+
+ KNS::Engine *engine = new KNS::Engine(d->newstuff, type, this);
+ KNS::DownloadDialog *d = new KNS::DownloadDialog( engine, this );
+ d->setType(type);
+
+ KNS::ProviderLoader *p = new KNS::ProviderLoader(this);
+ QObject::connect(p, SIGNAL(providersLoaded(Provider::List*)),
+ d, SLOT(slotProviders(Provider::List*)));
+
+ p->load(type, QString("http://download.kde.org/khotnewstuff/%1scripts-providers.xml").arg(appname));
+ d->exec();
+#endif
+}
+
+void WdgScriptsManager::slotResourceInstalled()
+{
+ // Delete KNewStuff's configuration entries. These entries reflect what has
+ // already been installed. As we cannot yet keep them in sync after uninstalling
+ // scripts, we deactivate the check marks entirely.
+ KGlobal::config()->deleteGroup("KNewStuffStatus");
+}
+
+}}
+
+#include "wdgscriptsmanager.moc"
diff --git a/lib/kross/main/wdgscriptsmanager.h b/lib/kross/main/wdgscriptsmanager.h
new file mode 100644
index 00000000..031d5b3c
--- /dev/null
+++ b/lib/kross/main/wdgscriptsmanager.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ * 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 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef WDGSCRIPTSMANAGER_H
+#define WDGSCRIPTSMANAGER_H
+
+#include "main/scriptaction.h"
+#include "main/wdgscriptsmanagerbase.h"
+
+class Scripting;
+
+namespace Kross { namespace Api {
+
+class ScriptGUIClient;
+class WdgScriptsManagerPrivate;
+
+/**
+@author Cyrille Berger
+*/
+class WdgScriptsManager : public WdgScriptsManagerBase
+{
+ Q_OBJECT
+ public:
+ WdgScriptsManager(ScriptGUIClient* scr, QWidget* parent = 0, const char* name = 0, WFlags fl = 0);
+ ~WdgScriptsManager();
+ public slots:
+ void slotLoadScript();
+ void slotInstallScript();
+ void slotUninstallScript();
+ void slotExecuteScript();
+ void slotUnloadScript();
+ void slotGetNewScript();
+ void slotSelectionChanged(QListViewItem*);
+ private slots:
+ void slotFillScriptsList();
+ void slotResourceInstalled();
+ private:
+ WdgScriptsManagerPrivate* d;
+ void addItem(ScriptActionCollection* collection);
+ QListViewItem* addItem(ScriptAction::Ptr, QListViewItem* parentitem, QListViewItem* afteritem);
+};
+
+}}
+
+#endif
diff --git a/lib/kross/main/wdgscriptsmanagerbase.ui b/lib/kross/main/wdgscriptsmanagerbase.ui
new file mode 100644
index 00000000..18ab2b23
--- /dev/null
+++ b/lib/kross/main/wdgscriptsmanagerbase.ui
@@ -0,0 +1,247 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgScriptsManagerBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>WdgScriptsManagerBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>181</width>
+ <height>467</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Scripts Manager</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KListView">
+ <property name="name">
+ <cstring>scriptsList</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>2</hsizetype>
+ <vsizetype>2</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KToolBar">
+ <property name="name">
+ <cstring>toolBar</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnExec</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Execute</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line2</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnLoad</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Load</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnUnload</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Unload</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnInstall</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Install</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnUninstall</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Uninstall</string>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>line4</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnNewStuff</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Get More Scripts</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KToolBar</class>
+ <header location="local">ktoolbar.h</header>
+ <sizehint>
+ <width>20</width>
+ <height>100</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+ <includehint>ktoolbar.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>