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