00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "scriptguiclient.h"
00021 #include "manager.h"
00022 #include "../api/interpreter.h"
00023 #include "wdgscriptsmanager.h"
00024
00025 #include <kapplication.h>
00026 #include <kpopupmenu.h>
00027 #include <kstandarddirs.h>
00028 #include <kmimetype.h>
00029 #include <kmessagebox.h>
00030 #include <kfiledialog.h>
00031 #include <klocale.h>
00032 #include <kurl.h>
00033 #include <ktar.h>
00034 #include <kstandarddirs.h>
00035
00036 #include <kio/netaccess.h>
00037
00038 using namespace Kross::Api;
00039
00040 namespace Kross { namespace Api {
00041
00043 class ScriptGUIClientPrivate
00044 {
00045 public:
00050 KXMLGUIClient* guiclient;
00051
00055 QWidget* parent;
00056
00061 QMap<QString, ScriptActionCollection*> collections;
00062 };
00063
00064 }}
00065
00066 ScriptGUIClient::ScriptGUIClient(KXMLGUIClient* guiclient, QWidget* parent)
00067 : QObject( parent )
00068 , KXMLGUIClient( guiclient )
00069 , d( new ScriptGUIClientPrivate() )
00070 {
00071 krossdebug( QString("ScriptGUIClient::ScriptGUIClient() Ctor") );
00072
00073 d->guiclient = guiclient;
00074 d->parent = parent;
00075
00076 setInstance( ScriptGUIClient::instance() );
00077
00078
00079 new KAction(i18n("Execute Script File..."), 0, 0, this, SLOT(executeScriptFile()), actionCollection(), "executescriptfile");
00080
00081
00082 new KAction(i18n("Scripts Manager..."), 0, 0, this, SLOT(showScriptManager()), actionCollection(), "configurescripts");
00083
00084
00085 d->collections.replace("installedscripts",
00086 new ScriptActionCollection(i18n("Scripts"), actionCollection(), "installedscripts") );
00087 d->collections.replace("loadedscripts",
00088 new ScriptActionCollection(i18n("Loaded"), actionCollection(), "loadedscripts") );
00089 d->collections.replace("executedscripts",
00090 new ScriptActionCollection(i18n("History"), actionCollection(), "executedscripts") );
00091
00092 reloadInstalledScripts();
00093 }
00094
00095 ScriptGUIClient::~ScriptGUIClient()
00096 {
00097 krossdebug( QString("ScriptGUIClient::~ScriptGUIClient() Dtor") );
00098 for(QMap<QString, ScriptActionCollection*>::Iterator it = d->collections.begin(); it != d->collections.end(); ++it)
00099 delete it.data();
00100 delete d;
00101 }
00102
00103 bool ScriptGUIClient::hasActionCollection(const QString& name)
00104 {
00105 return d->collections.contains(name);
00106 }
00107
00108 ScriptActionCollection* ScriptGUIClient::getActionCollection(const QString& name)
00109 {
00110 return d->collections[name];
00111 }
00112
00113 QMap<QString, ScriptActionCollection*> ScriptGUIClient::getActionCollections()
00114 {
00115 return d->collections;
00116 }
00117
00118 void ScriptGUIClient::addActionCollection(const QString& name, ScriptActionCollection* collection)
00119 {
00120 removeActionCollection(name);
00121 d->collections.replace(name, collection);
00122 }
00123
00124 bool ScriptGUIClient::removeActionCollection(const QString& name)
00125 {
00126 if(d->collections.contains(name)) {
00127 ScriptActionCollection* c = d->collections[name];
00128 d->collections.remove(name);
00129 delete c;
00130 return true;
00131 }
00132 return false;
00133 }
00134
00135 void ScriptGUIClient::reloadInstalledScripts()
00136 {
00137 ScriptActionCollection* installedcollection = d->collections["installedscripts"];
00138 if(installedcollection)
00139 installedcollection->clear();
00140
00141 QCString partname = d->guiclient->instance()->instanceName();
00142 QStringList files = KGlobal::dirs()->findAllResources("data", partname + "/scripts/*/*.rc");
00143
00144 for(QStringList::iterator it = files.begin(); it != files.end(); ++it)
00145 loadScriptConfigFile(*it);
00146 }
00147
00148 bool ScriptGUIClient::installScriptPackage(const QString& scriptpackagefile)
00149 {
00150 krossdebug( QString("Install script package: %1").arg(scriptpackagefile) );
00151 KTar archive( scriptpackagefile );
00152 if(! archive.open(IO_ReadOnly)) {
00153 KMessageBox::sorry(0, i18n("Could not read the package \"%1\".").arg(scriptpackagefile));
00154 return false;
00155 }
00156
00157 QCString partname = d->guiclient->instance()->instanceName();
00158 QString destination = KGlobal::dirs()->saveLocation("data", partname + "/scripts/", true);
00159
00160 if(destination.isNull()) {
00161 krosswarning("ScriptGUIClient::installScriptPackage() Failed to determinate location where the scriptpackage should be installed to!");
00162 return false;
00163 }
00164
00165 QString packagename = QFileInfo(scriptpackagefile).baseName();
00166 destination += packagename;
00167
00168 if( QDir(destination).exists() ) {
00169 if( KMessageBox::warningContinueCancel(0,
00170 i18n("A script package with the name \"%1\" already exists. Replace this package?" ).arg(packagename),
00171 i18n("Replace")) != KMessageBox::Continue )
00172 return false;
00173
00174 if(! KIO::NetAccess::del(destination, 0) ) {
00175 KMessageBox::sorry(0, i18n("Could not uninstall this script package. You may not have sufficient permissions to delete the folder \"%1\".").arg(destination));
00176 return false;
00177 }
00178 }
00179
00180 krossdebug( QString("Copy script-package to destination directory: %1").arg(destination) );
00181 const KArchiveDirectory* archivedir = archive.directory();
00182 archivedir->copyTo(destination, true);
00183
00184 reloadInstalledScripts();
00185 return true;
00186 }
00187
00188 bool ScriptGUIClient::uninstallScriptPackage(const QString& scriptpackagepath)
00189 {
00190 if(! KIO::NetAccess::del(scriptpackagepath, 0) ) {
00191 KMessageBox::sorry(0, i18n("Could not uninstall this script package. You may not have sufficient permissions to delete the folder \"%1\".").arg(scriptpackagepath));
00192 return false;
00193 }
00194 reloadInstalledScripts();
00195 return true;
00196 }
00197
00198 bool ScriptGUIClient::loadScriptConfigFile(const QString& scriptconfigfile)
00199 {
00200 krossdebug( QString("ScriptGUIClient::loadScriptConfig file=%1").arg(scriptconfigfile) );
00201
00202 QDomDocument domdoc;
00203 QFile file(scriptconfigfile);
00204 if(! file.open(IO_ReadOnly)) {
00205 krosswarning( QString("ScriptGUIClient::loadScriptConfig(): Failed to read scriptconfigfile: %1").arg(scriptconfigfile) );
00206 return false;
00207 }
00208 bool ok = domdoc.setContent(&file);
00209 file.close();
00210 if(! ok) {
00211 krosswarning( QString("ScriptGUIClient::loadScriptConfig(): Failed to parse scriptconfigfile: %1").arg(scriptconfigfile) );
00212 return false;
00213 }
00214
00215 return loadScriptConfigDocument(scriptconfigfile, domdoc);
00216 }
00217
00218 bool ScriptGUIClient::loadScriptConfigDocument(const QString& scriptconfigfile, const QDomDocument &document)
00219 {
00220 ScriptActionCollection* installedcollection = d->collections["installedscripts"];
00221 QDomNodeList nodelist = document.elementsByTagName("ScriptAction");
00222 uint nodelistcount = nodelist.count();
00223 for(uint i = 0; i < nodelistcount; i++) {
00224 ScriptAction::Ptr action = new ScriptAction(scriptconfigfile, nodelist.item(i).toElement());
00225
00226 if(installedcollection) {
00227 ScriptAction::Ptr otheraction = installedcollection->action( action->name() );
00228 if(otheraction) {
00229
00230
00231
00232 if(action->version() < otheraction->version() && action->version() >= 0) {
00233
00234
00235 continue;
00236 }
00237 else if(action->version() > otheraction->version() && otheraction->version() >= 0) {
00238
00239
00240 otheraction->finalize();
00241 installedcollection->detach(otheraction);
00242
00243 }
00244 else {
00245
00246
00247 krosswarning( QString("Kross::Api::ScriptGUIClient::loadScriptConfigDocument: There exists already a scriptaction with name \"%1\". Added anyway...").arg(action->name()) );
00248 }
00249 }
00250 installedcollection->attach( action );
00251 }
00252
00253 connect(action.data(), SIGNAL( failed(const QString&, const QString&) ),
00254 this, SLOT( executionFailed(const QString&, const QString&) ));
00255 connect(action.data(), SIGNAL( success() ),
00256 this, SLOT( successfullyExecuted() ));
00257 connect(action.data(), SIGNAL( activated(const Kross::Api::ScriptAction*) ), SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
00258 }
00259 emit collectionChanged(installedcollection);
00260 return true;
00261 }
00262
00263 void ScriptGUIClient::setXMLFile(const QString& file, bool merge, bool setXMLDoc)
00264 {
00265 KXMLGUIClient::setXMLFile(file, merge, setXMLDoc);
00266 }
00267
00268 void ScriptGUIClient::setDOMDocument(const QDomDocument &document, bool merge)
00269 {
00270 ScriptActionCollection* installedcollection = d->collections["installedscripts"];
00271 if(! merge && installedcollection)
00272 installedcollection->clear();
00273
00274 KXMLGUIClient::setDOMDocument(document, merge);
00275 loadScriptConfigDocument(xmlFile(), document);
00276 }
00277
00278 void ScriptGUIClient::successfullyExecuted()
00279 {
00280 const ScriptAction* action = dynamic_cast< const ScriptAction* >( QObject::sender() );
00281 if(action) {
00282 emit executionFinished(action);
00283 ScriptActionCollection* executedcollection = d->collections["executedscripts"];
00284 if(executedcollection) {
00285 ScriptAction* actionptr = const_cast< ScriptAction* >( action );
00286 executedcollection->detach(actionptr);
00287 executedcollection->attach(actionptr);
00288 emit collectionChanged(executedcollection);
00289 }
00290 }
00291 }
00292
00293 void ScriptGUIClient::executionFailed(const QString& errormessage, const QString& tracedetails)
00294 {
00295 const ScriptAction* action = dynamic_cast< const ScriptAction* >( QObject::sender() );
00296 if(action)
00297 emit executionFinished(action);
00298 if(tracedetails.isEmpty())
00299 KMessageBox::error(0, errormessage);
00300 else
00301 KMessageBox::detailedError(0, errormessage, tracedetails);
00302 }
00303
00304 KURL ScriptGUIClient::openScriptFile(const QString& caption)
00305 {
00306 QStringList mimetypes;
00307 QMap<QString, InterpreterInfo*> infos = Manager::scriptManager()->getInterpreterInfos();
00308 for(QMap<QString, InterpreterInfo*>::Iterator it = infos.begin(); it != infos.end(); ++it)
00309 mimetypes.append( it.data()->getMimeTypes().join(" ").stripWhiteSpace() );
00310
00311 KFileDialog* filedialog = new KFileDialog(
00312 QString::null,
00313 mimetypes.join(" "),
00314 0,
00315 "ScriptGUIClientFileDialog",
00316 true
00317 );
00318 if(! caption.isNull())
00319 filedialog->setCaption(caption);
00320 if( filedialog->exec() )
00321 return filedialog->selectedURL();
00322 return KURL();
00323 }
00324
00325 bool ScriptGUIClient::loadScriptFile()
00326 {
00327 KURL url = openScriptFile( i18n("Load Script File") );
00328 if(url.isValid()) {
00329 ScriptActionCollection* loadedcollection = d->collections["loadedscripts"];
00330 if(loadedcollection) {
00331 ScriptAction::Ptr action = new ScriptAction( url.path() );
00332 connect(action.data(), SIGNAL( failed(const QString&, const QString&) ),
00333 this, SLOT( executionFailed(const QString&, const QString&) ));
00334 connect(action.data(), SIGNAL( success() ),
00335 this, SLOT( successfullyExecuted() ));
00336 connect(action.data(), SIGNAL( activated(const Kross::Api::ScriptAction*) ), SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
00337
00338 loadedcollection->detach(action);
00339 loadedcollection->attach(action);
00340 return true;
00341 }
00342 }
00343 return false;
00344 }
00345
00346 bool ScriptGUIClient::executeScriptFile()
00347 {
00348 KURL url = openScriptFile( i18n("Execute Script File") );
00349 if(url.isValid())
00350 return executeScriptFile( url.path() );
00351 return false;
00352 }
00353
00354 bool ScriptGUIClient::executeScriptFile(const QString& file)
00355 {
00356 krossdebug( QString("Kross::Api::ScriptGUIClient::executeScriptFile() file='%1'").arg(file) );
00357
00358 ScriptAction::Ptr action = new ScriptAction(file);
00359 return executeScriptAction(action);
00360 }
00361
00362 bool ScriptGUIClient::executeScriptAction(ScriptAction::Ptr action)
00363 {
00364 connect(action.data(), SIGNAL( failed(const QString&, const QString&) ),
00365 this, SLOT( executionFailed(const QString&, const QString&) ));
00366 connect(action.data(), SIGNAL( success() ),
00367 this, SLOT( successfullyExecuted() ));
00368 connect(action.data(), SIGNAL( activated(const Kross::Api::ScriptAction*) ), SIGNAL( executionStarted(const Kross::Api::ScriptAction*)));
00369 action->activate();
00370 bool ok = action->hadException();
00371 action->finalize();
00372 return ok;
00373 }
00374
00375 void ScriptGUIClient::showScriptManager()
00376 {
00377 KDialogBase* dialog = new KDialogBase(d->parent, "", true, i18n("Scripts Manager"), KDialogBase::Close);
00378 WdgScriptsManager* wsm = new WdgScriptsManager(this, dialog);
00379 dialog->setMainWidget(wsm);
00380 dialog->resize( QSize(360, 320).expandedTo(dialog->minimumSizeHint()) );
00381 dialog->show();
00382 }
00383
00384 #include "scriptguiclient.moc"