You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
15 KiB
385 lines
15 KiB
/***************************************************************************
|
|
* 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 TQWidget widget.
|
|
*/
|
|
TQWidget* parent;
|
|
|
|
/**
|
|
* Map of \a ScriptActionCollection instances the \a ScriptGUIClient
|
|
* is attached to.
|
|
*/
|
|
TQMap<TQString, ScriptActionCollection*> collections;
|
|
};
|
|
|
|
}}
|
|
|
|
ScriptGUIClient::ScriptGUIClient(KXMLGUIClient* guiclient, TQWidget* parent)
|
|
: TQObject( parent )
|
|
, KXMLGUIClient( guiclient )
|
|
, d( new ScriptGUIClientPrivate() ) // initialize d-pointer class
|
|
{
|
|
krossdebug( TQString("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, TQT_SLOT(executeScriptFile()), actionCollection(), "executescriptfile");
|
|
|
|
// acion to show the ScriptManagerGUI dialog.
|
|
new KAction(i18n("Scripts Manager..."), 0, 0, this, TQT_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( TQString("ScriptGUIClient::~ScriptGUIClient() Dtor") );
|
|
for(TQMap<TQString, ScriptActionCollection*>::Iterator it = d->collections.begin(); it != d->collections.end(); ++it)
|
|
delete it.data();
|
|
delete d;
|
|
}
|
|
|
|
bool ScriptGUIClient::hasActionCollection(const TQString& name)
|
|
{
|
|
return d->collections.contains(name);
|
|
}
|
|
|
|
ScriptActionCollection* ScriptGUIClient::getActionCollection(const TQString& name)
|
|
{
|
|
return d->collections[name];
|
|
}
|
|
|
|
TQMap<TQString, ScriptActionCollection*> ScriptGUIClient::getActionCollections()
|
|
{
|
|
return d->collections;
|
|
}
|
|
|
|
void ScriptGUIClient::addActionCollection(const TQString& name, ScriptActionCollection* collection)
|
|
{
|
|
removeActionCollection(name);
|
|
d->collections.replace(name, collection);
|
|
}
|
|
|
|
bool ScriptGUIClient::removeActionCollection(const TQString& 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();
|
|
|
|
TQCString partname = d->guiclient->instance()->instanceName();
|
|
TQStringList files = KGlobal::dirs()->findAllResources("data", partname + "/scripts/*/*.rc");
|
|
//files.sort();
|
|
for(TQStringList::iterator it = files.begin(); it != files.end(); ++it)
|
|
loadScriptConfigFile(*it);
|
|
}
|
|
|
|
bool ScriptGUIClient::installScriptPackage(const TQString& scriptpackagefile)
|
|
{
|
|
krossdebug( TQString("Install script package: %1").tqarg(scriptpackagefile) );
|
|
KTar archive( scriptpackagefile );
|
|
if(! archive.open(IO_ReadOnly)) {
|
|
KMessageBox::sorry(0, i18n("Could not read the package \"%1\".").tqarg(scriptpackagefile));
|
|
return false;
|
|
}
|
|
|
|
TQCString partname = d->guiclient->instance()->instanceName();
|
|
TQString destination = KGlobal::dirs()->saveLocation("data", partname + "/scripts/", true);
|
|
//TQString 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;
|
|
}
|
|
|
|
TQString packagename = TQFileInfo(scriptpackagefile).baseName();
|
|
destination += packagename; // add the packagename to the name of the destination-directory.
|
|
|
|
if( TQDir(destination).exists() ) {
|
|
if( KMessageBox::warningContinueCancel(0,
|
|
i18n("A script package with the name \"%1\" already exists. Replace this package?" ).tqarg(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\".").tqarg(destination));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
krossdebug( TQString("Copy script-package to destination directory: %1").tqarg(destination) );
|
|
const KArchiveDirectory* archivedir = archive.directory();
|
|
archivedir->copyTo(destination, true);
|
|
|
|
reloadInstalledScripts();
|
|
return true;
|
|
}
|
|
|
|
bool ScriptGUIClient::uninstallScriptPackage(const TQString& 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\".").tqarg(scriptpackagepath));
|
|
return false;
|
|
}
|
|
reloadInstalledScripts();
|
|
return true;
|
|
}
|
|
|
|
bool ScriptGUIClient::loadScriptConfigFile(const TQString& scriptconfigfile)
|
|
{
|
|
krossdebug( TQString("ScriptGUIClient::loadScriptConfig file=%1").tqarg(scriptconfigfile) );
|
|
|
|
TQDomDocument domdoc;
|
|
TQFile file(scriptconfigfile);
|
|
if(! file.open(IO_ReadOnly)) {
|
|
krosswarning( TQString("ScriptGUIClient::loadScriptConfig(): Failed to read scriptconfigfile: %1").tqarg(scriptconfigfile) );
|
|
return false;
|
|
}
|
|
bool ok = domdoc.setContent(&file);
|
|
file.close();
|
|
if(! ok) {
|
|
krosswarning( TQString("ScriptGUIClient::loadScriptConfig(): Failed to parse scriptconfigfile: %1").tqarg(scriptconfigfile) );
|
|
return false;
|
|
}
|
|
|
|
return loadScriptConfigDocument(scriptconfigfile, domdoc);
|
|
}
|
|
|
|
bool ScriptGUIClient::loadScriptConfigDocument(const TQString& scriptconfigfile, const TQDomDocument &document)
|
|
{
|
|
ScriptActionCollection* installedcollection = d->collections["installedscripts"];
|
|
TQDomNodeList 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( TQString("Kross::Api::ScriptGUIClient::loadScriptConfigDocument: There exists already a scriptaction with name \"%1\". Added anyway...").tqarg(action->name()) );
|
|
}
|
|
}
|
|
installedcollection->attach( action );
|
|
}
|
|
|
|
connect(action.data(), TQT_SIGNAL( failed(const TQString&, const TQString&) ),
|
|
this, TQT_SLOT( executionFailed(const TQString&, const TQString&) ));
|
|
connect(action.data(), TQT_SIGNAL( success() ),
|
|
this, TQT_SLOT( successfullyExecuted() ));
|
|
connect(action.data(), TQT_SIGNAL( activated(const Kross::Api::ScriptAction*) ), TQT_SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
|
|
}
|
|
emit collectionChanged(installedcollection);
|
|
return true;
|
|
}
|
|
|
|
void ScriptGUIClient::setXMLFile(const TQString& file, bool merge, bool setXMLDoc)
|
|
{
|
|
KXMLGUIClient::setXMLFile(file, merge, setXMLDoc);
|
|
}
|
|
|
|
void ScriptGUIClient::setDOMDocument(const TQDomDocument &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* >( TQObject::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 TQString& errormessage, const TQString& tracedetails)
|
|
{
|
|
const ScriptAction* action = dynamic_cast< const ScriptAction* >( TQObject::sender() );
|
|
if(action)
|
|
emit executionFinished(action);
|
|
if(tracedetails.isEmpty())
|
|
KMessageBox::error(0, errormessage);
|
|
else
|
|
KMessageBox::detailedError(0, errormessage, tracedetails);
|
|
}
|
|
|
|
KURL ScriptGUIClient::openScriptFile(const TQString& caption)
|
|
{
|
|
TQStringList mimetypes;
|
|
TQMap<TQString, InterpreterInfo*> infos = Manager::scriptManager()->getInterpreterInfos();
|
|
for(TQMap<TQString, InterpreterInfo*>::Iterator it = infos.begin(); it != infos.end(); ++it)
|
|
mimetypes.append( it.data()->getMimeTypes().join(" ").stripWhiteSpace() );
|
|
|
|
KFileDialog* filedialog = new KFileDialog(
|
|
TQString(), // 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(), TQT_SIGNAL( failed(const TQString&, const TQString&) ),
|
|
this, TQT_SLOT( executionFailed(const TQString&, const TQString&) ));
|
|
connect(action.data(), TQT_SIGNAL( success() ),
|
|
this, TQT_SLOT( successfullyExecuted() ));
|
|
connect(action.data(), TQT_SIGNAL( activated(const Kross::Api::ScriptAction*) ), TQT_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 TQString& file)
|
|
{
|
|
krossdebug( TQString("Kross::Api::ScriptGUIClient::executeScriptFile() file='%1'").tqarg(file) );
|
|
|
|
ScriptAction::Ptr action = new ScriptAction(file);
|
|
return executeScriptAction(action);
|
|
}
|
|
|
|
bool ScriptGUIClient::executeScriptAction(ScriptAction::Ptr action)
|
|
{
|
|
connect(action.data(), TQT_SIGNAL( failed(const TQString&, const TQString&) ),
|
|
this, TQT_SLOT( executionFailed(const TQString&, const TQString&) ));
|
|
connect(action.data(), TQT_SIGNAL( success() ),
|
|
this, TQT_SLOT( successfullyExecuted() ));
|
|
connect(action.data(), TQT_SIGNAL( activated(const Kross::Api::ScriptAction*) ), TQT_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( TQSize(360, 320).expandedTo(dialog->tqminimumSizeHint()) );
|
|
dialog->show();
|
|
}
|
|
|
|
#include "scriptguiclient.moc"
|