00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "plugin.h"
00021
00022 #include <kaction.h>
00023 #include <kdebug.h>
00024 #include <kstandarddirs.h>
00025 #include <krun.h>
00026 #include <kxmlguifactory.h>
00027 #include <kactioncollection.h>
00028 #include <kross/core/manager.h>
00029 #include <kross/core/actioncollection.h>
00030 #include <kio/netaccess.h>
00031
00032 #include <QPointer>
00033
00034 using namespace Kross;
00035
00036 struct Object
00037 {
00038 QPointer<QObject> object;
00039 ChildrenInterface::Options options;
00040 Object(QObject* obj, ChildrenInterface::Options opt):object(obj),options(opt){}
00041 };
00042
00043
00045 class ScriptingPlugin::ScriptingPluginPrivate
00046 {
00047 public:
00048 QString collectionName;
00049 QString userActionsFile;
00050 QString referenceActionsDir;
00051 QHash<QString, Object> objects;
00052
00053 QDomElement menuFromName(QString const& name, const QDomDocument& document)
00054 {
00055 QDomElement menuBar = document.documentElement().firstChildElement("MenuBar");
00056 QDomElement menu = menuBar.firstChildElement("Menu");
00057 for(; !menu.isNull(); menu = menu.nextSiblingElement("Menu")) {
00058 if(menu.attribute("name") == name) {
00059 return menu;
00060 }
00061 }
00062 return QDomElement();
00063 }
00064 };
00065
00066 ScriptingPlugin::ScriptingPlugin(QObject* parent)
00067 : KParts::Plugin(parent)
00068 , d(new ScriptingPluginPrivate())
00069 {
00070 d->userActionsFile = KGlobal::dirs()->locateLocal("appdata", "scripts/scriptactions.rc");
00071 d->collectionName="scripting-plugin";
00072 }
00073
00074 ScriptingPlugin::ScriptingPlugin(const QString& collectionName, const QString& userActionsFile, const QString& referenceActionsDir, QObject* parent)
00075 : KParts::Plugin(parent)
00076 , d(new ScriptingPluginPrivate())
00077 {
00078 d->collectionName=collectionName;
00079 d->userActionsFile = userActionsFile;
00080 d->referenceActionsDir = referenceActionsDir;
00081 }
00082
00083 ScriptingPlugin::~ScriptingPlugin()
00084 {
00085 if (QFile::exists(d->userActionsFile))
00086 save();
00087
00088 Kross::ActionCollection* collection=Kross::Manager::self().actionCollection()->collection(d->collectionName);
00089 if (collection) {
00090 collection->setParentCollection(0);
00091 collection->deleteLater();
00092 }
00093
00094 delete d;
00095 }
00096
00097 void ScriptingPlugin::setDOMDocument(const QDomDocument &document, bool merge)
00098 {
00099 QDomDocument doc = buildDomDocument(document);
00100 KXMLGUIClient::setDOMDocument(doc, merge);
00101 }
00102
00103 void ScriptingPlugin::addObject(QObject* object, const QString& name)
00104 {
00105 QString n = name.isNull() ? object->objectName() : name;
00106 d->objects.insert(n, Object(object,ChildrenInterface::NoOption));
00107 }
00108
00109 void ScriptingPlugin::addObject(QObject* object, const QString& name, ChildrenInterface::Options options)
00110 {
00111 QString n = name.isNull() ? object->objectName() : name;
00112 d->objects.insert(n, Object(object,options));
00113 }
00114
00115 QDomDocument ScriptingPlugin::buildDomDocument(const QDomDocument& document)
00116 {
00117 Kross::ActionCollection* collection=Kross::Manager::self().actionCollection()->collection(d->collectionName);
00118 if (!collection) {
00119 collection=new Kross::ActionCollection(d->collectionName, Kross::Manager::self().actionCollection());
00120 }
00121
00122 QStringList allActionFiles = KGlobal::dirs()->findAllResources("appdata", "scripts/"+d->referenceActionsDir+"/*.rc");
00123
00124 int pos=allActionFiles.indexOf(d->userActionsFile);
00125 if (pos!=-1)
00126 allActionFiles.append(allActionFiles.takeAt(pos));
00127 else if (QFile::exists(d->userActionsFile))
00128 allActionFiles.append(d->userActionsFile);
00129
00130 QStringList searchPath=KGlobal::dirs()->findDirs("appdata", "scripts/"+d->referenceActionsDir);
00131 foreach(const QString &file, allActionFiles) {
00132 QFile f(file);
00133 if (!f.open(QIODevice::ReadOnly))
00134 continue;
00135
00136 collection->readXml(&f, searchPath+QStringList(QFileInfo(f).absolutePath()));
00137 f.close();
00138
00139 }
00140
00141 QDomDocument doc(document);
00142 buildDomDocument(doc, collection);
00143
00144 return doc;
00145 }
00146
00147 void ScriptingPlugin::buildDomDocument(QDomDocument& document,
00148 Kross::ActionCollection* collection)
00149 {
00150 QDomElement menuElement = d->menuFromName(collection->name(), document);
00151
00152 foreach(Kross::Action* action, collection->actions()) {
00153 QHashIterator<QString, Object> i(d->objects);
00154 while(i.hasNext()) {
00155 i.next();
00156 action->addObject(i.value().object, i.key(), i.value().options);
00157 }
00158
00159
00160 if(menuElement.isNull()) {
00161 menuElement = document.createElement("Menu");
00162 menuElement.setAttribute("name", collection->name());
00163 menuElement.setAttribute("noMerge", "0");
00164
00165 QDomElement textElement = document.createElement("text");
00166 textElement.appendChild(document.createTextNode(collection->text()));
00167 menuElement.appendChild(textElement);
00168
00169 Kross::ActionCollection* parentCollection = collection->parentCollection();
00170 QDomElement root;
00171 if(parentCollection) {
00172 QDomElement parentMenuElement = d->menuFromName(parentCollection->name(), document);
00173 if(!parentMenuElement.isNull())
00174 root=parentMenuElement;
00175 }
00176 if (root.isNull())
00177 root=document.documentElement().firstChildElement("MenuBar");
00178 root.appendChild(menuElement);
00179 }
00180
00181
00182 QDomElement newActionElement = document.createElement("Action");
00183 newActionElement.setAttribute("name", action->name());
00184
00185 menuElement.appendChild(newActionElement);
00186
00187
00188 KAction* adaptor=new KAction(action->text(), action);
00189 connect (adaptor,SIGNAL(triggered()),action,SLOT(trigger()));
00190 adaptor->setEnabled(action->isEnabled());
00191 adaptor->setIcon(action->icon());
00192 actionCollection()->addAction(action->name(), adaptor);
00193 }
00194
00195 foreach(const QString &collectionname, collection->collections()) {
00196 Kross::ActionCollection* c = collection->collection(collectionname);
00197 if(c->isEnabled()) {
00198 buildDomDocument(document, c);
00199 }
00200 }
00201 }
00202
00203 void ScriptingPlugin::save()
00204 {
00205 QFile f(d->userActionsFile);
00206 if(!f.open(QIODevice::WriteOnly))
00207 return;
00208
00209 Kross::ActionCollection* collection=Kross::Manager::self().actionCollection()->collection(d->collectionName);
00210 bool collectionEmpty = !collection||(collection->actions().empty()&&collection->collections().empty());
00211
00212 if( !collectionEmpty ) {
00213 QStringList searchPath=KGlobal::dirs()->findDirs("appdata", "scripts/"+d->referenceActionsDir);
00214 searchPath.append(QFileInfo(d->userActionsFile).absolutePath());
00215 if( collection->writeXml(&f, 2, searchPath) ) {
00216 kDebug() << "Successfully saved file: " << d->userActionsFile;
00217 }
00218 }
00219 else {
00220 QTextStream out(&f);
00221 QString xml=
00222 "<!-- "
00223 "\n"
00224 "Collection name attribute represents the name of the menu, e.g., to use menu \"File\" use \"file\" or \"Help\" use \"help\". You can add new menus."
00225 "\n\n\n"
00226 "If you type a relative script file beware the this script is located in $KDEHOME/share/apps/applicationname/"
00227 "\n\n"
00228 "The following example adds an action with the text \"Export...\" into the \"File\" menu"
00229 "\n\n"
00230 "<KrossScripting>"
00231 "\n"
00232 "<collection name=\"file\" text=\"File\" comment=\"File menu\">"
00233 "\n"
00234 "<script name=\"export\" text=\"Export...\" comment=\"Export content\" file=\"export.py\" />"
00235 "\n"
00236 "</collection>"
00237 "\n"
00238 "</KrossScripting>"
00239 "\n"
00240 "-->";
00241
00242
00243 out << xml;
00244 }
00245 f.close();
00246 }
00247
00248 void ScriptingPlugin::slotEditScriptActions()
00249 {
00250 if(!KIO::NetAccess::exists(KUrl(d->userActionsFile), KIO::NetAccess::SourceSide, 0)) {
00251 KUrl dir = KUrl(d->userActionsFile).directory();
00252 KIO::NetAccess::mkdir(dir, 0);
00253
00254 save();
00255 }
00256
00257
00258 KRun::runUrl(KUrl(d->userActionsFile), QString("text/plain"), 0, false);
00259 }
00260
00261 void ScriptingPlugin::slotResetScriptActions()
00262 {
00263 KIO::NetAccess::del(KUrl(d->userActionsFile), 0);
00264 }
00265
00266 #include "plugin.moc"