• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Kross

actioncollection.cpp
Go to the documentation of this file.
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 <QtCore/QHash>
00025 #include <QtCore/QStringList>
00026 #include <QtCore/QPointer>
00027 #include <QtCore/QIODevice>
00028 #include <QtCore/QFile>
00029 #include <QtCore/QFileInfo>
00030 #include <QtXml/QDomAttr>
00031 
00032 #include <kicon.h>
00033 #include <klocalizedstring.h>
00034 
00035 using namespace Kross;
00036 
00037 namespace Kross {
00038 
00040     class ActionCollection::Private
00041     {
00042         public:
00043             QPointer<ActionCollection> parent;
00044             QHash< QString, QPointer<ActionCollection> > collections;
00045             QStringList collectionnames;
00046 
00047             QList< Action* > actionList;
00048             QHash< QString, Action* > actionMap;
00049 
00050             QString text;
00051             QString description;
00052             QString iconname;
00053             bool enabled;
00054             bool blockupdated;
00055 
00056             Private(ActionCollection* const p) : parent(p) {}
00057     };
00058 
00059 }
00060 
00061 ActionCollection::ActionCollection(const QString& name, ActionCollection* parent)
00062     : QObject(0)
00063     , d( new Private(0) )
00064 {
00065     setObjectName(name);
00066     d->text = name;
00067     d->enabled = true;
00068     d->blockupdated = false;
00069 
00070     setParentCollection(parent);
00071 }
00072 
00073 ActionCollection::~ActionCollection()
00074 {
00075     if ( d->parent ) {
00076         emit d->parent->collectionToBeRemoved(this, d->parent);
00077         d->parent->unregisterCollection( objectName() );
00078         emit d->parent->collectionRemoved( this, d->parent );
00079     }
00080     delete d;
00081 }
00082 
00083 QString ActionCollection::name() const { return objectName(); }
00084 
00085 QString ActionCollection::text() const { return d->text; }
00086 void ActionCollection::setText(const QString& text) { d->text = text; emit dataChanged(this); emitUpdated(); }
00087 
00088 QString ActionCollection::description() const { return d->description; }
00089 void ActionCollection::setDescription(const QString& description) { d->description = description; emit dataChanged(this); emitUpdated(); }
00090 
00091 QString ActionCollection::iconName() const { return d->iconname; }
00092 void ActionCollection::setIconName(const QString& iconname) { d->iconname = iconname; emit dataChanged(this); }
00093 QIcon ActionCollection::icon() const { return KIcon(d->iconname); }
00094 
00095 bool ActionCollection::isEnabled() const { return d->enabled; }
00096 void ActionCollection::setEnabled(bool enabled) { d->enabled = enabled; emit dataChanged(this); emitUpdated(); }
00097 
00098 ActionCollection* ActionCollection::parentCollection() const
00099 {
00100     return d->parent;
00101 }
00102 
00103 void ActionCollection::setParentCollection( ActionCollection *parent )
00104 {
00105     if ( d->parent ) {
00106         emit d->parent->collectionToBeRemoved(this, d->parent);
00107         d->parent->unregisterCollection( objectName() );
00108         setParent( 0 );
00109         emit d->parent->collectionRemoved( this, d->parent );
00110         d->parent = 0;
00111     }
00112     setParent(0);
00113     if ( parent ) {
00114         emit parent->collectionToBeInserted(this, parent);
00115         setParent( parent );
00116         d->parent = parent;
00117         parent->registerCollection( this );
00118         emit parent->collectionInserted( this, parent );
00119     }
00120     emitUpdated();
00121 }
00122 
00123 bool ActionCollection::hasCollection(const QString& name) const
00124 {
00125     return d->collections.contains(name);
00126 }
00127 
00128 ActionCollection* ActionCollection::collection(const QString& name) const
00129 {
00130     return d->collections.contains(name) ? d->collections[name] : QPointer<ActionCollection>(0);
00131 }
00132 
00133 QStringList ActionCollection::collections() const
00134 {
00135     return d->collectionnames;
00136 }
00137 
00138 void ActionCollection::registerCollection(ActionCollection* collection)
00139 {
00140     Q_ASSERT(collection);
00141     const QString name = collection->objectName();
00142     //Q_ASSERT( !name.isNull() );
00143     if (!d->collections.contains(name))
00144     {
00145         d->collections.insert(name, collection);
00146         d->collectionnames.append(name);
00147     }
00148     connectSignals(collection, true);
00149     emitUpdated();
00150 }
00151 
00152 void ActionCollection::unregisterCollection(const QString& name)
00153 {
00154     if( ! d->collections.contains(name) )
00155         return;
00156     ActionCollection* collection = d->collections[name];
00157     d->collectionnames.removeAll(name);
00158     d->collections.remove(name);
00159     connectSignals(collection, false);
00160     emitUpdated();
00161 }
00162 
00163 QList<Action*> ActionCollection::actions() const
00164 {
00165     return d->actionList;
00166 }
00167 
00168 Action* ActionCollection::action(const QString& name) const
00169 {
00170     return d->actionMap.contains(name) ? d->actionMap[name] : 0;
00171 }
00172 
00173 void ActionCollection::addAction(Action* action)
00174 {
00175     Q_ASSERT( action && ! action->objectName().isEmpty() );
00176     addAction(action->objectName(), action);
00177 }
00178 
00179 void ActionCollection::addAction(const QString& name, Action* action)
00180 {
00181     Q_ASSERT( action && ! name.isEmpty() );
00182     emit actionToBeInserted(action, this);
00183     if( d->actionMap.contains(name) )
00184         d->actionList.removeAll( d->actionMap[name] );
00185     d->actionMap.insert(name, action);
00186     d->actionList.append(action);
00187     action->setParent(this); // in case it is not set
00188     connectSignals(action, true);
00189     emit actionInserted(action, this);
00190     emitUpdated();
00191 }
00192 
00193 void ActionCollection::removeAction(const QString& name)
00194 {
00195     if( ! d->actionMap.contains(name) )
00196         return;
00197     Action* action = d->actionMap[name];
00198     connectSignals(action, false);
00199     emit actionToBeRemoved(action, this);
00200     d->actionList.removeAll(action);
00201     d->actionMap.remove(name);
00202     //krossdebug( QString("ActionCollection::removeAction: %1 %2").arg(action->name()).arg(action->parent()->objectName()) );
00203     action->setParent( 0 );
00204     emit actionRemoved(action, this);
00205     emitUpdated();
00206 }
00207 
00208 void ActionCollection::removeAction(Action* action)
00209 {
00210     Q_ASSERT( action && ! action->objectName().isEmpty() );
00211     if( ! d->actionMap.contains(action->objectName()) ) {
00212         Q_ASSERT( ! d->actionList.contains(action) );
00213         return;
00214     }
00215     removeAction( action->objectName() );
00216 }
00217 
00218 void ActionCollection::connectSignals(Action *action, bool conn)
00219 {
00220     if ( conn ) {
00221         connect(action, SIGNAL(dataChanged(Action*)), this, SIGNAL(dataChanged(Action*)));
00222         connect(action, SIGNAL(updated()), this, SLOT(emitUpdated()));
00223     } else {
00224         disconnect(action, SIGNAL(dataChanged(Action*)), this, SIGNAL(dataChanged(Action*)));
00225         disconnect(action, SIGNAL(updated()), this, SLOT(emitUpdated()));
00226     }
00227 }
00228 
00229 void ActionCollection::connectSignals(ActionCollection *collection, bool conn)
00230 {
00231     if ( conn ) {
00232         connect(collection, SIGNAL(dataChanged(Action*)), this, SIGNAL(dataChanged(Action*)));
00233         connect(collection, SIGNAL(dataChanged(ActionCollection*)), this, SIGNAL(dataChanged(ActionCollection*)));
00234 
00235         connect(collection, SIGNAL(collectionToBeInserted(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionToBeInserted(ActionCollection*, ActionCollection*)));
00236         connect(collection, SIGNAL(collectionInserted(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionInserted(ActionCollection*, ActionCollection*)));
00237         connect(collection, SIGNAL(collectionToBeRemoved(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionToBeRemoved(ActionCollection*, ActionCollection*)));
00238         connect(collection, SIGNAL(collectionRemoved(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionRemoved(ActionCollection*, ActionCollection*)));
00239 
00240         connect(collection, SIGNAL(actionToBeInserted(Action*, ActionCollection*)), this, SIGNAL(actionToBeInserted(Action*, ActionCollection*)));
00241         connect(collection, SIGNAL(actionInserted(Action*, ActionCollection*)), this, SIGNAL(actionInserted(Action*, ActionCollection*)));
00242         connect(collection, SIGNAL(actionToBeRemoved(Action*, ActionCollection*)), this, SIGNAL(actionToBeRemoved(Action*, ActionCollection*)));
00243         connect(collection, SIGNAL(actionRemoved(Action*, ActionCollection*)), this, SIGNAL(actionRemoved(Action*, ActionCollection*)));
00244         connect(collection, SIGNAL(updated()), this, SLOT(emitUpdated()));
00245     } else {
00246         disconnect(collection, SIGNAL(dataChanged(ActionCollection*)), this, SIGNAL(dataChanged(ActionCollection*)));
00247 
00248         disconnect(collection, SIGNAL(collectionToBeInserted(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionToBeInserted(ActionCollection*, ActionCollection*)));
00249         disconnect(collection, SIGNAL(collectionInserted(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionInserted(ActionCollection*, ActionCollection*)));
00250         disconnect(collection, SIGNAL(collectionToBeRemoved(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionToBeRemoved(ActionCollection*, ActionCollection*)));
00251         disconnect(collection, SIGNAL(collectionRemoved(ActionCollection*, ActionCollection*)), this, SIGNAL(collectionRemoved(ActionCollection*, ActionCollection*)));
00252 
00253         disconnect(collection, SIGNAL(actionToBeInserted(Action*, ActionCollection*)), this, SIGNAL(actionToBeInserted(Action*, ActionCollection*)));
00254         disconnect(collection, SIGNAL(actionInserted(Action*, ActionCollection*)), this, SIGNAL(actionInserted(Action*, ActionCollection*)));
00255         disconnect(collection, SIGNAL(actionToBeRemoved(Action*, ActionCollection*)), this, SIGNAL(actionToBeRemoved(Action*, ActionCollection*)));
00256         disconnect(collection, SIGNAL(actionRemoved(Action*, ActionCollection*)), this, SIGNAL(actionRemoved(Action*, ActionCollection*)));
00257         disconnect(collection, SIGNAL(updated()), this, SLOT(emitUpdated()));
00258     }
00259 }
00260 
00261 void ActionCollection::emitUpdated()
00262 {
00263     if (!d->blockupdated) emit updated();
00264 }
00265 
00266 /*********************************************************************
00267  * Unserialize from XML / QIODevice / file / resource to child
00268  * ActionCollection's and Action's this ActionCollection has.
00269  */
00270 
00271 bool ActionCollection::readXml(const QDomElement& element, const QDir& directory)
00272 {
00273     return readXml(element, QStringList(directory.absolutePath()));
00274 }
00275 
00276 bool ActionCollection::readXml(const QDomElement& element, const QStringList& searchPath)
00277 {
00278     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00279         krossdebug( QString("ActionCollection::readXml tagName=\"%1\"").arg(element.tagName()) );
00280     #endif
00281 
00282     d->blockupdated = true; // block updated() signals and emit it only once if everything is done
00283     bool ok = true;
00284     QDomNodeList list = element.childNodes();
00285     const int size = list.size();
00286     for(int i = 0; i < size; ++i) {
00287         QDomElement elem = list.item(i).toElement();
00288         if( elem.isNull() ) continue;
00289 
00290         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00291             krossdebug( QString("  ActionCollection::readXml child=%1 tagName=\"%2\"").arg(i).arg(elem.tagName()) );
00292         #endif
00293 
00294         if( elem.tagName() == "collection") {
00295             const QString name = elem.attribute("name");
00296             const QByteArray text = elem.attribute("text").toUtf8();
00297             const QByteArray description = elem.attribute("comment").toUtf8();
00298             const QString iconname = elem.attribute("icon");
00299             bool enabled = QVariant(elem.attribute("enabled","true")).toBool();
00300             ActionCollection* c = d->collections.contains(name) ? d->collections[name] : QPointer<ActionCollection>(0);
00301             if( ! c )
00302                 c = new ActionCollection(name, this);
00303 
00304             c->setText( text.isEmpty() ? name : i18n( text ) );
00305             c->setDescription( description.isEmpty() ? c->text() : i18n( description ) );
00306             c->setIconName( iconname );
00307 
00308             if( ! enabled )
00309                 c->setEnabled(false);
00310             if( ! c->readXml(elem, searchPath) )
00311                 ok = false;
00312         }
00313         else if( elem.tagName() == "script") {
00314             QString name = elem.attribute("name");
00315             Action* a = dynamic_cast< Action* >( action(name) );
00316             if( a ) {
00317                 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00318                     krossdebug( QString("  ActionCollection::readXml Updating Action \"%1\"").arg(a->objectName()) );
00319                 #endif
00320             }
00321             else {
00322                 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00323                     krossdebug( QString("  ActionCollection::readXml Creating Action \"%1\"").arg(name) );
00324                 #endif
00325 
00326                 a = new Action(this, name);
00327                 addAction(name, a);
00328                 connect(a, SIGNAL( started(Kross::Action*) ), &Manager::self(), SIGNAL( started(Kross::Action*)) );
00329                 connect(a, SIGNAL( finished(Kross::Action*) ), &Manager::self(), SIGNAL( finished(Kross::Action*) ));
00330             }
00331             a->fromDomElement(elem, searchPath);
00332         }
00333         //else if( ! fromXml(elem) ) ok = false;
00334     }
00335 
00336     d->blockupdated = false; // unblock signals
00337     emitUpdated();
00338     return ok;
00339 }
00340 
00341 bool ActionCollection::readXml(QIODevice* device, const QDir& directory)
00342 {
00343     return readXml(device, QStringList(directory.absolutePath()));
00344 }
00345 
00346 bool ActionCollection::readXml(QIODevice* device, const QStringList& searchPath)
00347 {
00348     QString errMsg;
00349     int errLine, errCol;
00350     QDomDocument document;
00351     bool ok = document.setContent(device, false, &errMsg, &errLine, &errCol);
00352     if( ! ok ) {
00353         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00354             krosswarning( QString("ActionCollection::readXml Error at line %1 in col %2: %3").arg(errLine).arg(errCol).arg(errMsg) );
00355         #endif
00356         return false;
00357     }
00358     return readXml(document.documentElement(), searchPath);
00359 }
00360 
00361 bool ActionCollection::readXmlFile(const QString& file)
00362 {
00363     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00364         krossdebug( QString("ActionCollection::readXmlFile file=\"%1\"").arg(file) );
00365     #endif
00366 
00367     QFile f(file);
00368     if( ! f.open(QIODevice::ReadOnly) ) {
00369         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00370             krosswarning( QString("ActionCollection::readXmlFile reading file \"%1\" failed.").arg(file) );
00371         #endif
00372         return false;
00373     }
00374     bool ok = readXml(&f, QFileInfo(file).dir());
00375     f.close();
00376 
00377     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00378         if( ! ok )
00379             krosswarning( QString("ActionCollection::readXmlFile parsing XML content of file \"%1\" failed.").arg(file) );
00380     #endif
00381     return ok;
00382 }
00383 
00384 /*********************************************************************
00385  * Serialize from child ActionCollection's and Action's this
00386  * ActionCollection has to XML / QIODevice / file / resource.
00387  */
00388 
00389 QDomElement ActionCollection::writeXml()
00390 {
00391     return writeXml(QStringList());
00392 }
00393 
00394 QDomElement ActionCollection::writeXml(const QStringList& searchPath)
00395 {
00396     #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00397         krossdebug( QString("ActionCollection::writeXml collection.objectName=\"%1\"").arg(objectName()) );
00398     #endif
00399 
00400     QDomDocument document;
00401     QDomElement element = document.createElement("collection");
00402     if( ! objectName().isNull() )
00403         element.setAttribute("name", objectName());
00404     if( ! text().isNull() && text() != objectName() )
00405         element.setAttribute("text", text());
00406     if( ! d->description.isNull() )
00407         element.setAttribute("comment", d->description);
00408     if( ! d->iconname.isNull() )
00409         element.setAttribute("icon", d->iconname);
00410     if( ! d->enabled )
00411         element.setAttribute("enabled", d->enabled);
00412 
00413     foreach(Action* a, actions()) {
00414         Q_ASSERT(a);
00415         #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00416             krossdebug( QString("  ActionCollection::writeXml action.objectName=\"%1\" action.file=\"%2\"").arg(a->objectName()).arg(a->file()) );
00417         #endif
00418         QDomElement e = a->toDomElement(searchPath);
00419         if( ! e.isNull() )
00420             element.appendChild(e);
00421     }
00422 
00423     foreach(const QString &name, d->collectionnames) {
00424         ActionCollection* c = d->collections[name];
00425         if( ! c ) continue;
00426         QDomElement e = c->writeXml(searchPath);
00427         if( ! e.isNull() )
00428             element.appendChild(e);
00429     }
00430 
00431     return element;
00432 }
00433 
00434 bool ActionCollection::writeXml(QIODevice* device, int indent)
00435 {
00436     return writeXml(device, indent, QStringList());
00437 }
00438 
00439 bool ActionCollection::writeXml(QIODevice* device, int indent, const QStringList& searchPath)
00440 {
00441     QDomDocument document;
00442     QDomElement root = document.createElement("KrossScripting");
00443 
00444     foreach(Action* a, actions()) {
00445         QDomElement e = a->toDomElement(searchPath);
00446         if( ! e.isNull() )
00447             root.appendChild(e);
00448     }
00449 
00450     foreach(const QString &name, d->collectionnames) {
00451         ActionCollection* c = d->collections[name];
00452         if( ! c ) continue;
00453         QDomElement e = c->writeXml(searchPath);
00454         if( ! e.isNull() )
00455             root.appendChild(e);
00456     }
00457 
00458     document.appendChild(root);
00459     return device->write( document.toByteArray(indent) ) != -1;
00460 }
00461 
00462 #include "actioncollection.moc"

Kross

Skip menu "Kross"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal