Kross
plugin.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2008 Paulo Moura Guedes <moura@kdewebdev.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 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 //move userActionsFile to the end so that it updates existing actions and adds new ones. 00124 int pos=allActionFiles.indexOf(d->userActionsFile); 00125 if (pos!=-1) 00126 allActionFiles.append(allActionFiles.takeAt(pos)); 00127 else if (QFile::exists(d->userActionsFile)) //in case d->userActionsFile isn't in the standard local dir 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 // Create and append new Menu element if doesn't exist 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 // Create and append new Action element 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 //TODO very funny! this should use ui/view.h instead --Nick 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"
KDE 4.6 API Reference