00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00034 using namespace Kross;
00035
00036 namespace Kross {
00037
00039 class ActionCollection::Private
00040 {
00041 public:
00042 QPointer<ActionCollection> parent;
00043 QHash< QString, QPointer<ActionCollection> > collections;
00044 QStringList collectionnames;
00045
00046 QList< Action* > actionList;
00047 QHash< QString, Action* > actionMap;
00048
00049 QString text;
00050 QString description;
00051 QString iconname;
00052 bool enabled;
00053
00054 Private(ActionCollection* const p) : parent(p) {}
00055 };
00056
00057 }
00058
00059 ActionCollection::ActionCollection(const QString& name, ActionCollection* parent)
00060 : QObject(parent)
00061 , d( new Private(parent) )
00062 {
00063 setObjectName(name);
00064 d->text = name;
00065 d->enabled = true;
00066 if( d->parent )
00067 d->parent->registerCollection(this);
00068 }
00069
00070 ActionCollection::~ActionCollection()
00071 {
00072 if( d->parent )
00073 d->parent->unregisterCollection(objectName());
00074 delete d;
00075 }
00076
00077 QString ActionCollection::name() const { return objectName(); }
00078
00079 QString ActionCollection::text() const { return d->text; }
00080 void ActionCollection::setText(const QString& text) { d->text = text; emit updated(); }
00081
00082 QString ActionCollection::description() const { return d->description; }
00083 void ActionCollection::setDescription(const QString& description) { d->description = description; emit updated(); }
00084
00085 QString ActionCollection::iconName() const { return d->iconname; }
00086 void ActionCollection::setIconName(const QString& iconname) { d->iconname = iconname; }
00087 QIcon ActionCollection::icon() const { return KIcon(d->iconname); }
00088
00089 bool ActionCollection::isEnabled() const { return d->enabled; }
00090 void ActionCollection::setEnabled(bool enabled) { d->enabled = enabled; emit updated(); }
00091
00092 ActionCollection* ActionCollection::parentCollection() const
00093 {
00094 return d->parent;
00095 }
00096
00097 bool ActionCollection::hasCollection(const QString& name) const
00098 {
00099 return d->collections.contains(name);
00100 }
00101
00102 ActionCollection* ActionCollection::collection(const QString& name) const
00103 {
00104 return d->collections.contains(name) ? d->collections[name] : QPointer<ActionCollection>(0);
00105 }
00106
00107 QStringList ActionCollection::collections() const
00108 {
00109 return d->collectionnames;
00110 }
00111
00112 void ActionCollection::registerCollection(ActionCollection* collection)
00113 {
00114 Q_ASSERT(collection);
00115 const QString name = collection->objectName();
00116
00117 d->collections.insert(name, collection);
00118 d->collectionnames.append(name);
00119 connect(collection, SIGNAL(updated()), this, SIGNAL(updated()));
00120
00121 }
00122
00123 void ActionCollection::unregisterCollection(const QString& name)
00124 {
00125 if( ! d->collections.contains(name) )
00126 return;
00127 ActionCollection* collection = d->collections[name];
00128 d->collectionnames.removeAll(name);
00129 d->collections.remove(name);
00130 disconnect(collection, SIGNAL(updated()), this, SIGNAL(updated()));
00131
00132 }
00133
00134 QList<Action*> ActionCollection::actions() const
00135 {
00136 return d->actionList;
00137 }
00138
00139 Action* ActionCollection::action(const QString& name) const
00140 {
00141 return d->actionMap.contains(name) ? d->actionMap[name] : 0;
00142 }
00143
00144 void ActionCollection::addAction(Action* action)
00145 {
00146 Q_ASSERT( action && ! action->objectName().isEmpty() );
00147 addAction(action->objectName(), action);
00148 }
00149
00150 void ActionCollection::addAction(const QString& name, Action* action)
00151 {
00152 Q_ASSERT( action && ! name.isEmpty() );
00153 if( d->actionMap.contains(name) )
00154 d->actionList.removeAll( d->actionMap[name] );
00155 d->actionMap.insert(name, action);
00156 d->actionList.append(action);
00157 connect(action, SIGNAL(updated()), this, SIGNAL(updated()));
00158 emit updated();
00159 }
00160
00161 void ActionCollection::removeAction(const QString& name)
00162 {
00163 if( ! d->actionMap.contains(name) )
00164 return;
00165 Action* action = d->actionMap[name];
00166 d->actionList.removeAll(action);
00167 d->actionMap.remove(name);
00168 disconnect(action, SIGNAL(updated()), this, SIGNAL(updated()));
00169 emit updated();
00170 }
00171
00172 void ActionCollection::removeAction(Action* action)
00173 {
00174 Q_ASSERT( action && ! action->objectName().isEmpty() );
00175 const QString name = action->objectName();
00176 if( ! d->actionMap.contains(name) )
00177 return;
00178 d->actionList.removeAll(action);
00179 d->actionMap.remove(name);
00180 disconnect(action, SIGNAL(updated()), this, SIGNAL(updated()));
00181 emit updated();
00182 }
00183
00184
00185
00186
00187
00188
00189 bool ActionCollection::readXml(const QDomElement& element, const QDir& directory)
00190 {
00191 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00192 krossdebug( QString("ActionCollection::readXml tagName=\"%1\"").arg(element.tagName()) );
00193 #endif
00194
00195 blockSignals(true);
00196 bool ok = true;
00197 QDomNodeList list = element.childNodes();
00198 const int size = list.size();
00199 for(int i = 0; i < size; ++i) {
00200 QDomElement elem = list.item(i).toElement();
00201 if( elem.isNull() ) continue;
00202
00203 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00204 krossdebug( QString(" ActionCollection::readXml child=%1 tagName=\"%2\"").arg(i).arg(elem.tagName()) );
00205 #endif
00206
00207 if( elem.tagName() == "collection") {
00208 const QString name = elem.attribute("name");
00209 const QString text = elem.attribute("text");
00210 const QString description = elem.attribute("comment");
00211 const QString iconname = elem.attribute("icon");
00212 bool enabled = QVariant(elem.attribute("enabled","true")).toBool();
00213 ActionCollection* c = d->collections.contains(name) ? d->collections[name] : QPointer<ActionCollection>(0);
00214 if( ! c )
00215 c = new ActionCollection(name, this);
00216 c->setText( text.isEmpty() ? name : text );
00217 c->setDescription( description.isEmpty() ? c->text() : description );
00218 c->setIconName( iconname );
00219
00220 if( ! enabled )
00221 c->setEnabled(false);
00222 if( ! c->readXml(elem, directory) )
00223 ok = false;
00224 }
00225 else if( elem.tagName() == "script") {
00226 QString name = elem.attribute("name");
00227 Action* a = dynamic_cast< Action* >( action(name) );
00228 if( a ) {
00229 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00230 krossdebug( QString(" ActionCollection::readXml Updating Action \"%1\"").arg(a->objectName()) );
00231 #endif
00232 }
00233 else {
00234 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00235 krossdebug( QString(" ActionCollection::readXml Creating Action \"%1\"").arg(name) );
00236 #endif
00237
00238 a = new Action(this, name, directory);
00239 addAction(name, a);
00240 connect(a, SIGNAL( started(Kross::Action*) ), &Manager::self(), SIGNAL( started(Kross::Action*)) );
00241 connect(a, SIGNAL( finished(Kross::Action*) ), &Manager::self(), SIGNAL( finished(Kross::Action*) ));
00242 }
00243 a->fromDomElement(elem);
00244 }
00245
00246 }
00247
00248 blockSignals(false);
00249 emit updated();
00250 return ok;
00251 }
00252
00253 bool ActionCollection::readXml(QIODevice* device, const QDir& directory)
00254 {
00255 QString errMsg;
00256 int errLine, errCol;
00257 QDomDocument document;
00258 bool ok = document.setContent(device, false, &errMsg, &errLine, &errCol);
00259 if( ! ok ) {
00260 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00261 krosswarning( QString("ActionCollection::readXml Error at line %1 in col %2: %3").arg(errLine).arg(errCol).arg(errMsg) );
00262 #endif
00263 return false;
00264 }
00265 return readXml(document.documentElement(), directory);
00266 }
00267
00268 bool ActionCollection::readXmlFile(const QString& file)
00269 {
00270 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00271 krossdebug( QString("ActionCollection::readXmlFile file=\"%1\"").arg(file) );
00272 #endif
00273
00274 QFile f(file);
00275 if( ! f.open(QIODevice::ReadOnly) ) {
00276 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00277 krosswarning( QString("ActionCollection::readXmlFile reading file \"%1\" failed.").arg(file) );
00278 #endif
00279 return false;
00280 }
00281 bool ok = readXml(&f, QFileInfo(file).dir());
00282 f.close();
00283
00284 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00285 if( ! ok )
00286 krosswarning( QString("ActionCollection::readXmlFile parsing XML content of file \"%1\" failed.").arg(file) );
00287 #endif
00288 return ok;
00289 }
00290
00291
00292
00293
00294
00295
00296 QDomElement ActionCollection::writeXml()
00297 {
00298 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00299 krossdebug( QString("ActionCollection::writeXml collection.objectName=\"%1\"").arg(objectName()) );
00300 #endif
00301
00302 QDomDocument document;
00303 QDomElement element = document.createElement("collection");
00304 if( ! objectName().isNull() )
00305 element.setAttribute("name", objectName());
00306 if( ! text().isNull() && text() != objectName() )
00307 element.setAttribute("text", text());
00308 if( ! d->description.isNull() )
00309 element.setAttribute("comment", d->description);
00310 if( ! d->iconname.isNull() )
00311 element.setAttribute("icon", d->iconname);
00312 if( ! d->enabled )
00313 element.setAttribute("enabled", d->enabled);
00314
00315 foreach(Action* a, actions()) {
00316 Q_ASSERT(a);
00317 #ifdef KROSS_ACTIONCOLLECTION_DEBUG
00318 krossdebug( QString(" ActionCollection::writeXml action.objectName=\"%1\" action.file=\"%2\"").arg(a->objectName()).arg(a->file()) );
00319 #endif
00320 QDomElement e = a->toDomElement();
00321 if( ! e.isNull() )
00322 element.appendChild(e);
00323 }
00324
00325 foreach(const QString &name, d->collectionnames) {
00326 ActionCollection* c = d->collections[name];
00327 if( ! c ) continue;
00328 QDomElement e = c->writeXml();
00329 if( ! e.isNull() )
00330 element.appendChild(e);
00331 }
00332
00333 return element;
00334 }
00335
00336 bool ActionCollection::writeXml(QIODevice* device, int indent)
00337 {
00338 QDomDocument document;
00339 QDomElement root = document.createElement("KrossScripting");
00340
00341 foreach(Action* a, actions()) {
00342 QDomElement e = a->toDomElement();
00343 if( ! e.isNull() )
00344 root.appendChild(e);
00345 }
00346
00347 foreach(const QString &name, d->collectionnames) {
00348 ActionCollection* c = d->collections[name];
00349 if( ! c ) continue;
00350 QDomElement e = c->writeXml();
00351 if( ! e.isNull() )
00352 root.appendChild(e);
00353 }
00354
00355 document.appendChild(root);
00356 return device->write( document.toByteArray(indent) ) != -1;
00357 }
00358
00359 #include "actioncollection.moc"