DocumentProtector.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <QCoreApplication>
00027 # include <QObject>
00028 # include <QEvent>
00029 # include <QMutex>
00030 # include <QMutexLocker>
00031 # include <QSemaphore>
00032 # include <QThread>
00033 # include <QWaitCondition>
00034 #endif
00035
00036 #include "DocumentProtector.h"
00037
00038 #include <App/Document.h>
00039 #include <App/DocumentObject.h>
00040 #include <Base/Exception.h>
00041
00042 using namespace Sandbox;
00043
00044
00045 namespace Sandbox {
00046
00047 static const int QT_CUSTOM_EVENT_PROTECTOR = 10000;
00048
00049 class AbstractCustomProtectorEvent : public QEvent
00050 {
00051 public:
00052 AbstractCustomProtectorEvent()
00053 : QEvent(QEvent::Type(QT_CUSTOM_EVENT_PROTECTOR)), semaphore(0)
00054 {
00055 }
00056 ~AbstractCustomProtectorEvent()
00057 {
00058 if (semaphore)
00059 semaphore->release();
00060 }
00061 virtual void execute() = 0;
00062
00063 QSemaphore* semaphore;
00064 };
00065
00066 class CustomAddObjectEvent : public AbstractCustomProtectorEvent
00067 {
00068 public:
00069 CustomAddObjectEvent(App::DocumentObject** o, App::Document* d, const std::string& type, const std::string& name)
00070 : obj(o), doc(d), type(type), name(name)
00071 {
00072 }
00073 ~CustomAddObjectEvent()
00074 {
00075 }
00076 void execute()
00077 {
00078 *obj = doc->addObject(this->type.c_str(), this->name.c_str());
00079 }
00080
00081 protected:
00082 App::DocumentObject** obj;
00083 App::Document* doc;
00084 std::string type, name;
00085 };
00086
00087 class CustomRemoveObjectEvent : public AbstractCustomProtectorEvent
00088 {
00089 public:
00090 CustomRemoveObjectEvent(App::Document* d, const std::string& n) : doc(d), name(n)
00091 {
00092 }
00093 ~CustomRemoveObjectEvent()
00094 {
00095 }
00096 void execute()
00097 {
00098 doc->remObject(this->name.c_str());
00099 }
00100
00101 protected:
00102 App::Document* doc;
00103 std::string name;
00104 };
00105
00106 class CustomRecomputeEvent : public AbstractCustomProtectorEvent
00107 {
00108 public:
00109 CustomRecomputeEvent(App::Document* d) : doc(d)
00110 {
00111 }
00112 ~CustomRecomputeEvent()
00113 {
00114 }
00115 void execute()
00116 {
00117 doc->recompute();
00118 }
00119
00120 protected:
00121 App::Document* doc;
00122 };
00123
00124 class CustomPropertyEvent : public AbstractCustomProtectorEvent
00125 {
00126 public:
00127 CustomPropertyEvent(App::Property& p, const App::Property& v)
00128 : property(p), value(v)
00129 {
00130 }
00131 ~CustomPropertyEvent()
00132 {
00133 }
00134 void execute()
00135 {
00136 property.Paste(value);
00137 }
00138
00139 protected:
00140 App::Property& property;
00141 const App::Property& value;
00142 };
00143
00144 class CustomCallableEvent : public AbstractCustomProtectorEvent
00145 {
00146 public:
00147 CustomCallableEvent(const AbstractCallable& call)
00148 : callable(call)
00149 {
00150 }
00151 ~CustomCallableEvent()
00152 {
00153 }
00154 void execute()
00155 {
00156 callable();
00157 }
00158
00159 protected:
00160 const AbstractCallable& callable;
00161 };
00162
00163 class DocumentReceiver : public QObject
00164 {
00165 public:
00166 DocumentReceiver(QObject *parent = 0) : QObject(parent)
00167 {
00168 }
00169 ~DocumentReceiver()
00170 {
00171 }
00172
00173 static DocumentReceiver *globalInstance();
00174
00175 protected:
00176 void customEvent(QEvent*);
00177 void postEventAndWait(QEvent*);
00178
00179
00180 friend class DocumentProtector;
00181 friend class DocumentObjectProtector;
00182 };
00183
00184 Q_GLOBAL_STATIC(DocumentReceiver, theInstance)
00185
00186 DocumentReceiver *DocumentReceiver::globalInstance()
00187 {
00188 return theInstance();
00189 }
00190
00191
00192 void DocumentReceiver::postEventAndWait(QEvent* e)
00193 {
00194 QThread *currentThread = QThread::currentThread();
00195 QThread *thr = this->thread();
00196
00197 if (currentThread == thr) {
00198
00199 QCoreApplication::sendEvent(this, e);
00200 delete e;
00201 }
00202 else {
00203
00204
00205 QSemaphore semaphore;
00206 static_cast<AbstractCustomProtectorEvent*>(e)->semaphore = &semaphore;
00207 QCoreApplication::postEvent(this, e);
00208
00209 semaphore.acquire();
00210 }
00211 }
00212
00213 void DocumentReceiver::customEvent(QEvent* e)
00214 {
00215 if ((int)e->type() == QT_CUSTOM_EVENT_PROTECTOR) {
00216 static_cast<AbstractCustomProtectorEvent*>(e)->execute();
00217 }
00218 }
00219
00220 }
00221
00222 DocumentProtector::DocumentProtector(App::Document* doc)
00223 : App::DocumentObserver(doc)
00224 {
00225 }
00226
00227 DocumentProtector::~DocumentProtector()
00228 {
00229 }
00230
00231 void DocumentProtector::init()
00232 {
00233
00234 DocumentReceiver::globalInstance()->
00235 moveToThread(QCoreApplication::instance()->thread());
00236 }
00237
00238 void DocumentProtector::slotCreatedDocument(const App::Document& Doc)
00239 {
00240 }
00241
00242 void DocumentProtector::slotDeletedDocument(const App::Document& Doc)
00243 {
00244 if (&Doc == getDocument()) {
00245 this->detachDocument();
00246 }
00247 }
00248
00249 void DocumentProtector::slotCreatedObject(const App::DocumentObject& Obj)
00250 {
00251 }
00252
00253 void DocumentProtector::slotDeletedObject(const App::DocumentObject& Obj)
00254 {
00255 }
00256
00257 void DocumentProtector::slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop)
00258 {
00259 }
00260
00261 void DocumentProtector::validate()
00262 {
00263 if (!this->getDocument())
00264 throw Base::Exception("Handled document is null");
00265 }
00266
00267 App::DocumentObject *DocumentProtector::addObject(const std::string& type, const std::string& name)
00268 {
00269 validate();
00270 App::DocumentObject* obj;
00271 DocumentReceiver::globalInstance()->postEventAndWait
00272 (new CustomAddObjectEvent(&obj, this->getDocument(), type, name));
00273 return obj;
00274 }
00275
00276 void DocumentProtector::removeObject(const std::string& name)
00277 {
00278 validate();
00279 DocumentReceiver::globalInstance()->postEventAndWait
00280 (new CustomRemoveObjectEvent(this->getDocument(), name));
00281 }
00282
00283 void DocumentProtector::recompute()
00284 {
00285 validate();
00286 DocumentReceiver::globalInstance()->postEventAndWait
00287 (new CustomRecomputeEvent(this->getDocument()));
00288 }
00289
00290
00291
00292 DocumentObjectProtector::DocumentObjectProtector(App::DocumentObject* o) : obj(o)
00293 {
00294 }
00295
00296 DocumentObjectProtector::~DocumentObjectProtector()
00297 {
00298 }
00299
00300 void DocumentObjectProtector::validate()
00301 {
00302 if (!obj)
00303 throw Base::Exception("Handled document object is null");
00304 }
00305
00306 App::DocumentObject* DocumentObjectProtector::getObject() const
00307 {
00308 return this->obj;
00309 }
00310
00311 bool DocumentObjectProtector::setProperty(const std::string& name, const App::Property& value)
00312 {
00313 validate();
00314 App::Property* prop = obj->getPropertyByName(name.c_str());
00315 if (!prop)
00316 return false;
00317 DocumentReceiver::globalInstance()->postEventAndWait(new CustomPropertyEvent(*prop, value));
00318 return true;
00319 }
00320
00321 void DocumentObjectProtector::execute(const AbstractCallable& call)
00322 {
00323 validate();
00324 DocumentReceiver::globalInstance()->postEventAndWait(new CustomCallableEvent(call));
00325 }
00326