/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include 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 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::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 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").arg(scriptpackagefile) ); KTar archive( scriptpackagefile ); if(! archive.open(IO_ReadOnly)) { KMessageBox::sorry(0, i18n("Could not read the package \"%1\".").arg(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?" ).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( TQString("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 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\".").arg(scriptpackagepath)); return false; } reloadInstalledScripts(); return true; } bool ScriptGUIClient::loadScriptConfigFile(const TQString& scriptconfigfile) { krossdebug( TQString("ScriptGUIClient::loadScriptConfig file=%1").arg(scriptconfigfile) ); TQDomDocument domdoc; TQFile file(scriptconfigfile); if(! file.open(IO_ReadOnly)) { krosswarning( TQString("ScriptGUIClient::loadScriptConfig(): Failed to read scriptconfigfile: %1").arg(scriptconfigfile) ); return false; } bool ok = domdoc.setContent(&file); file.close(); if(! ok) { krosswarning( TQString("ScriptGUIClient::loadScriptConfig(): Failed to parse scriptconfigfile: %1").arg(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...").arg(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 infos = Manager::scriptManager()->getInterpreterInfos(); for(TQMap::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'").arg(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->minimumSizeHint()) ); dialog->show(); } #include "scriptguiclient.moc"