Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
.
[graphlib.git] / DrawingWindow.cpp
index 76227ff..fb3561d 100644 (file)
@@ -36,9 +36,9 @@ public:
 
     QBasicTimer timer;
     QMutex imageMutex;
-    QMutex paintMutex;
-    QWaitCondition paintCondition;
-    bool painted;
+    QMutex syncMutex;
+    QWaitCondition syncCondition;
+    bool terminateThread;
     int lockCount;
 
     QImage *image;
@@ -66,6 +66,7 @@ public:
     void dirty(int x1, int y1, int x2, int y2);
     void dirty(const QRect &rect);
 
+    void update();
 };
 
 //--- DrawingWindow ----------------------------------------------------
@@ -155,19 +156,16 @@ void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
 
 bool DrawingWindow::sync(unsigned long time)
 {
-    bool ret;
-    d->safeLock(d->paintMutex);
-    d->safeLock(d->imageMutex);
-#if 1
-    d->dirty();                 // xxx
-#else
-    QApplication::postEvent(this, new QPaintEvent(this->rect()));
-    d->dirtyFlag = false;
-#endif
-    d->safeUnlock(d->imageMutex);
-    ret = d->paintCondition.wait(&d->paintMutex, time);
-    d->safeUnlock(d->paintMutex);
-    return ret;
+    bool synced;
+    d->safeLock(d->syncMutex);
+    if (d->terminateThread) {
+        synced = false;
+    } else {
+        qApp->postEvent(this, new QEvent(QEvent::User));
+        synced = d->syncCondition.wait(&d->syncMutex, time);
+    }
+    d->safeUnlock(d->syncMutex);
+    return synced;
 }
 
 void DrawingWindow::sleep(unsigned long secs)
@@ -189,11 +187,51 @@ void DrawingWindow::closeEvent(QCloseEvent *ev)
 {
     d->timer.stop();
     d->thread->terminate();
-    d->paintCondition.wakeAll();
+    d->syncMutex.lock();
+    d->terminateThread = true;  // this flag is needed for the case
+                                // where the following wakeAll() call
+                                // occurs between the
+                                // setTerminationEnable(false) and the
+                                // mutex lock in safeLock() called
+                                // from sync()
+    d->syncCondition.wakeAll();
+    d->syncMutex.unlock();
     QWidget::closeEvent(ev);
     d->thread->wait();
 }
 
+void DrawingWindow::customEvent(QEvent *)
+{
+    d->update();
+    qApp->sendPostedEvents(this, QEvent::UpdateLater);
+    qApp->sendPostedEvents(this, QEvent::UpdateRequest);
+    qApp->sendPostedEvents(this, QEvent::Paint);
+    qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
+                        QEventLoop::ExcludeSocketNotifiers |
+                        QEventLoop::DeferredDeletion |
+                        QEventLoop::X11ExcludeTimers);
+    qApp->flush();
+    qApp->syncX();
+    d->syncMutex.lock();
+    d->syncCondition.wakeAll();
+    d->syncMutex.unlock();
+}
+
+void DrawingWindow::keyPressEvent(QKeyEvent *ev)
+{
+    bool accept = true;
+    switch (ev->key()) {
+    case Qt::Key_Escape:
+        close();
+        break;
+    default:
+        accept = false;
+        break;
+    }
+    if (accept)
+        ev->accept();
+}
+
 void DrawingWindow::paintEvent(QPaintEvent *ev)
 {
     QPainter widgetPainter(this);
@@ -202,11 +240,6 @@ void DrawingWindow::paintEvent(QPaintEvent *ev)
     d->imageMutex.unlock();
     QRect rect = ev->rect();
     widgetPainter.drawImage(rect, imageCopy, rect);
-    if (rect == this->rect()) {
-        d->paintMutex.lock();
-        d->paintCondition.wakeAll();
-        d->paintMutex.unlock();
-    }
 }
 
 void DrawingWindow::showEvent(QShowEvent *ev)
@@ -219,12 +252,7 @@ void DrawingWindow::showEvent(QShowEvent *ev)
 void DrawingWindow::timerEvent(QTimerEvent *ev)
 {
     if (ev->timerId() == d->timer.timerId()) {
-        d->imageMutex.lock();
-        if (d->dirtyFlag) {
-            update(d->dirtyRect);
-            d->dirtyFlag = false;
-        }
-        d->imageMutex.unlock();
+        d->update();
         d->timer.start(d->paintInterval, this);
     } else {
         QWidget::timerEvent(ev);
@@ -236,6 +264,7 @@ void DrawingWindow::timerEvent(QTimerEvent *ev)
 DrawingWindowPrivate::DrawingWindowPrivate(DrawingWindow *w,
                                            DrawingWindow::ThreadFunction f)
     : q(w)
+    , terminateThread(false)
     , lockCount(0)
     , image(new QImage(q->width, q->height, QImage::Format_RGB32))
     , painter(new QPainter(image))
@@ -311,6 +340,17 @@ void DrawingWindowPrivate::dirty(const QRect &rect)
     }
 }
 
+void DrawingWindowPrivate::update()
+{
+    imageMutex.lock();
+    bool dirty = dirtyFlag;
+    QRect rect = dirtyRect;
+    dirtyFlag = false;
+    imageMutex.unlock();
+    if (dirty)
+        q->update(rect);
+}
+
 //--- DrawingThread ----------------------------------------------------
 
 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)