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