F:/KPlato/koffice/libs/kross/core/actioncollection.cpp

Aller à la documentation de ce fichier.
00001 /***************************************************************************
00002  * actioncollection.cpp
00003  * This file is part of the KDE project
00004  * copyright (C)2004-2006 by Sebastian Sauer (mail@dipe.org)
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  * You should have received a copy of the GNU Library General Public License
00015  * along with this program; see the file COPYING.  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 "actioncollection.h"
00021 #include "action.h"
00022 #include "manager.h"
00023 
00024 #include <QStringList>
00025 #include <QPointer>
00026 #include <QIODevice>
00027 #include <QFile>
00028 #include <QFileInfo>
00029 #include <QDomElement>
00030 
00031 //#include <kapplication.h>
00032 //#include <klocale.h>
00033 #include <kicon.h>
00034 #include <kmimetype.h>
00035 #include <kstandarddirs.h>
00036 
00037 using namespace Kross;
00038 
00039 namespace Kross {
00040 
00042     class ActionCollection::Private
00043     {
00044         public:
00045             QPointer<ActionCollection> parent;
00046             QHash< QString, QPointer<ActionCollection> > collections;
00047             QStringList collectionnames;
00048 
00049             QString text;
00050 
00051             Private(ActionCollection* const p) : parent(p) {}
00052     };
00053 
00054 }
00055 
00056 ActionCollection::ActionCollection(const QString& name, ActionCollection* parent)
00057     : KActionCollection(parent)
00058     , d( new Private(parent) )
00059 {
00060     setObjectName(name);
00061     d->text = name;
00062     if( d->parent )
00063         d->parent->registerCollection(this);
00064 }
00065 
00066 ActionCollection::~ActionCollection()
00067 {
00068     if( d->parent )
00069         d->parent->unregisterCollection(objectName());
00070     delete d;
00071 }
00072 
00073 QString ActionCollection::text() const { return d->text; }
00074 void ActionCollection::setText(const QString& text) { d->text = text; }
00075 
00076 ActionCollection* ActionCollection::parentCollection() const
00077 {
00078     return d->parent;
00079 }
00080 
00081 bool ActionCollection::hasCollection(const QString& name) const
00082 {
00083     return d->collections.contains(name);
00084 }
00085 
00086 ActionCollection* ActionCollection::collection(const QString& name) const
00087 {
00088     return d->collections[name];
00089 }
00090 
00091 QStringList ActionCollection::collections() const
00092 {
00093     return d->collectionnames;
00094 }
00095 
00096 void ActionCollection::registerCollection(ActionCollection* collection)
00097 {
00098     const QString name = collection->objectName();
00099     //Q_ASSERT( !name.isNull() );
00100     d->collections.insert(name, collection);
00101     d->collectionnames.append(name);
00102 }
00103 
00104 void ActionCollection::unregisterCollection(const QString& name)
00105 {
00106     d->collectionnames.removeAll(name);
00107     d->collections.remove(name);
00108 }
00109 
00110 /*********************************************************************
00111  * Unserialize from XML / QIODevice / file / resource to child
00112  * ActionCollection's and Action's this ActionCollection has.
00113  */
00114 
00115 bool ActionCollection::readXml(const QDomElement& element, const QDir& directory)
00116 {
00117     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00118         krossdebug( QString("ActionCollection::readXml tagName=\"%1\"").arg(element.tagName()) );
00119     #endif
00120 
00121     bool ok = true;
00122     QDomNodeList list = element.childNodes();
00123     const int size = list.size();
00124     for(int i = 0; i < size; ++i) {
00125         QDomElement elem = list.item(i).toElement();
00126         if( elem.isNull() ) continue;
00127 
00128         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00129             krossdebug( QString("  ActionCollection::readXml child=%1 tagName=\"%2\"").arg(i).arg(elem.tagName()) );
00130         #endif
00131 
00132         if( elem.tagName() == "collection") {
00133             const QString name = elem.attribute("name");
00134             const QString text = elem.attribute("text");
00135             ActionCollection* c = d->collections.contains(name) ? d->collections[name] : 0;
00136             if( ! c )
00137                 c = new ActionCollection(name, this);
00138             if( ! text.isNull() )
00139                 c->setText(text);
00140             if( ! c->readXml(elem) )
00141                 ok = false;
00142         }
00143         else if( elem.tagName() == "script") {
00144             QString name = elem.attribute("name");
00145 
00146             QString file = elem.attribute("file");
00147             if(! QFileInfo(file).exists()) {
00148                 QFileInfo fi(directory, file);
00149                 if( fi.exists() ) {
00150                     file = fi.absoluteFilePath();
00151                 }
00152                 else {
00153                     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00154                         krosswarning( QString("    ActionCollection::readXml Failed to find file \"%1\" in the script-tag with name=\"%2\"").arg(file).arg(name) );
00155                     #endif
00156                     //QString resource = KGlobal::dirs()->findResource("appdata", QString("scripts/%1/%2").arg(name).arg(f));
00157                     //if( ! resource.isNull() ) f = resource;
00158                     file = QString();
00159                 }
00160             }
00161 
00162             QString text = elem.attribute("text");
00163             if( text.isEmpty() )
00164                 text = file;
00165 
00166             QString description = elem.attribute("comment");
00167             if( description.isEmpty() )
00168                 description = text.isEmpty() ? name : text;
00169 
00170             QString icon = elem.attribute("icon");
00171             if( icon.isEmpty() )
00172                 icon = KMimeType::iconNameForUrl( KUrl(file) );
00173 
00174             QString interpreter = elem.attribute("interpreter");
00175 
00176             Action* a = dynamic_cast< Action* >( action(name) );
00177             if( a ) {
00178                 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00179                     krossdebug( QString("  ActionCollection::readXml Updating Action \"%1\"").arg(a->objectName()) );
00180                 #endif
00181             }
00182             else {
00183                 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00184                     krossdebug( QString("  ActionCollection::readXml Creating Action \"%1\"").arg(name) );
00185                 #endif
00186 
00187                 a = new Action(this, name);
00188                 //FIXME move that functionality direct to the Action ctor?
00189                 connect(a, SIGNAL( started(Kross::Action*) ), &Manager::self(), SIGNAL( started(Kross::Action*)) );
00190                 connect(a, SIGNAL( finished(Kross::Action*) ), &Manager::self(), SIGNAL( finished(Kross::Action*) ));
00191             }
00192 
00193             a->setText(text);
00194             a->setDescription(description);
00195             if( ! icon.isNull() )
00196                 a->setIcon(KIcon(icon));
00197             if( ! interpreter.isNull() )
00198                 a->setInterpreter(interpreter);
00199             a->setFile(file);
00200         }
00201         //else if( ! fromXml(elem) ) ok = false;
00202     }
00203     return ok;
00204 }
00205 
00206 bool ActionCollection::readXml(QIODevice* device, const QDir& directory)
00207 {
00208     QString errMsg;
00209     int errLine, errCol;
00210     QDomDocument document;
00211     bool ok = document.setContent(device, false, &errMsg, &errLine, &errCol);
00212     if( ! ok ) {
00213         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00214             krosswarning( QString("ActionCollection::readXml Error at line %1 in col %2: %3").arg(errLine).arg(errCol).arg(errMsg) );
00215         #endif
00216         return false;
00217     }
00218     return readXml(document.documentElement(), directory);
00219 }
00220 
00221 bool ActionCollection::readXmlFile(const QString& file)
00222 {
00223     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00224         krossdebug( QString("ActionCollection::readXmlFile file=\"%1\"").arg(file) );
00225     #endif
00226 
00227     QFile f(file);
00228     if( ! f.open(QIODevice::ReadOnly) ) {
00229         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00230             krosswarning( QString("ActionCollection::readXmlFile reading file \"%1\" failed.").arg(file) );
00231         #endif
00232         return false;
00233     }
00234     bool ok = readXml(&f, QFileInfo(file).dir());
00235     f.close();
00236 
00237     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00238         if( ! ok )
00239             krosswarning( QString("ActionCollection::readXmlFile parsing XML content of file \"%1\" failed.").arg(file) );
00240     #endif
00241     return ok;
00242 }
00243 
00244 bool ActionCollection::readXmlResource(const QByteArray& resource, const QString& filer)
00245 {
00246     //filer = KApplication::kApplication()->objectName() + "/scripts/*.rc";
00247     QStringList files = KGlobal::dirs()->findAllResources(resource, filer);
00248     //files.sort();
00249     bool ok = true;
00250     foreach(QString s, files)
00251         if( ! readXmlFile(s) )
00252             ok = false;
00253     return ok;
00254 }
00255 
00256 /*********************************************************************
00257  * Serialize from child ActionCollection's and Action's this
00258  * ActionCollection has to XML / QIODevice / file / resource.
00259  */
00260 
00261 QDomElement ActionCollection::writeXml()
00262 {
00263     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00264         krossdebug( QString("ActionCollection::writeXml collection.objectName=\"%1\"").arg(objectName()) );
00265     #endif
00266 
00267     QDomDocument document;
00268     QDomElement element = document.createElement("collection");
00269     if( ! objectName().isNull() )
00270         element.setAttribute("name", objectName());
00271     if( ! text().isNull() && text() != objectName() )
00272         element.setAttribute("text", text());
00273 
00274     foreach(QString name, d->collectionnames) {
00275         ActionCollection* c = d->collections[name];
00276         if( ! c ) continue;
00277         QDomElement e = c->writeXml();
00278         if( e.isNull() ) continue;
00279         element.appendChild(e);
00280     }
00281 
00282     foreach(KAction* action, actions()) {
00283         Action* a = dynamic_cast< Action* >(action);
00284         if( ! a ) continue;
00285 
00286         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00287             krossdebug( QString("  ActionCollection::writeXml action.objectName=\"%1\" action.file=\"%2\"").arg(a->objectName()).arg(a->file()) );
00288         #endif
00289 
00290         QDomElement e = document.createElement("script");
00291         e.setAttribute("name", a->objectName());
00292         e.setAttribute("text", a->text());
00293         e.setAttribute("comment", a->description());
00294         //FIXME hmmm... kde4's KIcon / Qt4's QIcon does not allow to reproduce the iconname?
00295         //e.setAttribute("icon", a->iconName());
00296         e.setAttribute("interpreter", a->interpreter());
00297         e.setAttribute("file", a->file());
00298         element.appendChild(e);
00299     }
00300 
00301     return element;
00302 }
00303 
00304 bool ActionCollection::writeXml(QIODevice* device, int indent)
00305 {
00306     QDomDocument document;
00307     document.documentElement().appendChild( writeXml() );
00308     return device->write( document.toByteArray(indent) ) != -1;
00309 }
00310 
00311 #if 0
00312 bool Manager::readConfig()
00313 {
00314     KConfig* config = KApplication::kApplication()->sessionConfig();
00315     krossdebug( QString("Manager::readConfig hasGroup=%1 isReadOnly=%2 isImmutable=%3 ConfigState=%4").arg(config->hasGroup("scripts")).arg(config->isReadOnly()).arg(config->isImmutable()).arg(config->getConfigState()) );
00316     if(! config->hasGroup("scripts"))
00317         return false;
00318 
00319     // we need to remember the current names, to be able to remove "expired" actions later.
00320     QStringList actionnames;
00321     foreach(KAction* a, d->actioncollection->actions())
00322         actionnames.append( a->objectName() );
00323 
00324     // iterate now through the items in the [scripts]-section
00325     config->setGroup("scripts");
00326     foreach(QString name, config->readEntry("names", QStringList())) {
00327         bool needsupdate = actionnames.contains( name );
00328         if( needsupdate )
00329             actionnames.removeAll( name );
00330 
00331         QString text = config->readEntry(QString("%1_text").arg(name).toLatin1());
00332         QString description = config->readEntry(QString("%1_description").arg(name).toLatin1());
00333         QString icon = config->readEntry(QString("%1_icon").arg(name).toLatin1());
00334         QString file = config->readEntry(QString("%1_file").arg(name).toLatin1());
00335         QString interpreter = config->readEntry(QString("%1_interpreter").arg(name).toLatin1());
00336 
00337         if( text.isEmpty() )
00338             text = file;
00339         if( description.isEmpty() )
00340             description = text.isEmpty() ? name : text;
00341         if( icon.isEmpty() )
00342             icon = KMimeType::iconNameForUrl( KUrl(file) );
00343 
00344         Action* action = needsupdate
00345             ? dynamic_cast< Action* >( d->actioncollection->action(name) )
00346             : new Action(d->actioncollection, name);
00347         Q_ASSERT(action);
00348 
00349         action->setText(text);
00350         action->setDescription(description);
00351         if( ! icon.isNull() )
00352             action->setIcon(KIcon(icon));
00353         if( ! interpreter.isNull() )
00354             action->setInterpreter(interpreter);
00355         action->setFile(file);
00356 
00357         connect(action, SIGNAL( started(Kross::Action*) ), this, SIGNAL( started(Kross::Action*)) );
00358         connect(action, SIGNAL( finished(Kross::Action*) ), this, SIGNAL( finished(Kross::Action*) ));
00359     }
00360 
00361     // remove actions that are not valid anymore
00362     foreach(QString n, actionnames) {
00363         KAction* a = d->actioncollection->action(n);
00364         Q_ASSERT(a);
00365         d->actioncollection->remove(a);
00366         delete a;
00367     }
00368 
00369     return true;
00370 }
00371 
00372 bool Manager::writeConfig()
00373 {
00374     KConfig* config = KApplication::kApplication()->sessionConfig();
00375     krossdebug( QString("Manager::writeConfig hasGroup=%1 isReadOnly=%2 isImmutable=%3 ConfigState=%4").arg(config->hasGroup("scripts")).arg(config->isReadOnly()).arg(config->isImmutable()).arg(config->getConfigState()) );
00376     if(config->isReadOnly())
00377         return false;
00378 
00379     config->deleteGroup("scripts"); // remove old entries
00380     config->setGroup("scripts"); // according to the documentation it's needed to re-set the group after delete.
00381 
00382     QStringList names;
00383     foreach(KAction* a, d->actioncollection->actions(QString::null)) {
00384         Action* action = static_cast< Action* >(a);
00385         const QString name = action->objectName();
00386         names << name;
00387         config->writeEntry(QString("%1_text").arg(name).toLatin1(), action->text());
00388         config->writeEntry(QString("%1_description").arg(name).toLatin1(), action->description());
00389 
00390         //TODO hmmm... kde4's KIcon / Qt4's QIcon does not allow to reproduce the iconname?
00391         //config->writeEntry(QString("%1_icon").arg(name).toLatin1(), action->icon());
00392 
00393         config->writeEntry(QString("%1_file").arg(name).toLatin1(), action->file());
00394         config->writeEntry(QString("%1_interpreter").arg(name).toLatin1(), action->interpreter());
00395     }
00396 
00397     config->writeEntry("names", names);
00398     //config->sync();
00399     return true;
00400 }
00401 #endif
00402 
00403 #include "actioncollection.moc"

Généré le Wed Nov 22 23:41:11 2006 pour KPlato par  doxygen 1.5.1-p1