1 #include "DrawingWindow.h"
2 #include <QApplication>
8 class DrawingThread: public QThread {
10 DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f);
11 void start_once(Priority priority = InheritPriority);
17 DrawingWindow &drawingWindow;
18 DrawingWindow::ThreadFunction threadFunction;
21 friend class DrawingWindow;
24 //--- DrawingWindow ----------------------------------------------------
26 DrawingWindow::DrawingWindow(ThreadFunction f, int w, int h)
34 DrawingWindow::DrawingWindow(QWidget *parent,
35 ThreadFunction f, int w, int h)
43 DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
44 ThreadFunction f, int w, int h)
45 : QWidget(parent, flags)
52 DrawingWindow::~DrawingWindow()
59 void DrawingWindow::setColor(float red, float green, float blue)
61 fgColor.setRgbF(red, green, blue);
65 void DrawingWindow::setColor(const char *name)
67 fgColor.setNamedColor(name);
71 void DrawingWindow::setBgColor(float red, float green, float blue)
73 bgColor.setRgbF(red, green, blue);
76 void DrawingWindow::setBgColor(const char *name)
78 bgColor.setNamedColor(name);
81 void DrawingWindow::clearGraph()
84 painter->fillRect(image->rect(), bgColor);
86 safeUnlock(imageMutex);
89 void DrawingWindow::drawPoint(int x, int y)
92 painter->drawPoint(x, y);
94 safeUnlock(imageMutex);
97 void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
100 painter->drawLine(x1, y1, x2, y2);
101 dirty(x1, y1, x2, y2);
102 safeUnlock(imageMutex);
105 void DrawingWindow::drawRect(int x1, int y1, int x2, int y2)
108 r.setCoords(x1, y1, x2 - 1, y2 - 1);
110 safeLock(imageMutex);
111 painter->drawRect(r);
112 r.adjust(0, 0, 1, 1);
114 safeUnlock(imageMutex);
117 void DrawingWindow::fillRect(int x1, int y1, int x2, int y2)
119 painter->setBrush(fgColor);
120 drawRect(x1, y1, x2, y2);
121 painter->setBrush(Qt::NoBrush);
124 void DrawingWindow::drawCircle(int x, int y, int r)
127 rect.setCoords(x - r, y - r, x + r - 1, y + r - 1);
128 safeLock(imageMutex);
129 painter->drawEllipse(rect);
130 rect.adjust(0, 0, 1, 1);
132 safeUnlock(imageMutex);
135 void DrawingWindow::fillCircle(int x, int y, int r)
137 painter->setBrush(fgColor);
139 painter->setBrush(Qt::NoBrush);
142 void DrawingWindow::drawText(int x, int y, const char *text)
144 QRect r(image->rect());
146 safeLock(imageMutex);
147 painter->drawText(r, 0, text, &r);
149 safeUnlock(imageMutex);
152 bool DrawingWindow::sync(unsigned long time)
156 if (terminateThread) {
159 qApp->postEvent(this, new QEvent(QEvent::User));
160 synced = syncCondition.wait(&syncMutex, time);
162 safeUnlock(syncMutex);
166 void DrawingWindow::closeGraph()
168 qApp->postEvent(this, new QCloseEvent());
171 void DrawingWindow::sleep(unsigned long secs)
173 DrawingThread::sleep(secs);
176 void DrawingWindow::msleep(unsigned long msecs)
178 DrawingThread::msleep(msecs);
181 void DrawingWindow::usleep(unsigned long usecs)
183 DrawingThread::usleep(usecs);
186 void DrawingWindow::closeEvent(QCloseEvent *ev)
188 qDebug(">>>CLOSING<<<\n");
190 qDebug(">>> %c <<<\n", x++);
192 qDebug(">>> %c <<<\n", x++);
194 qDebug(">>> %c <<<\n", x++);
196 qDebug(">>> %c <<<\n", x++);
197 terminateThread = true; // this flag is needed for the case
198 // where the following wakeAll() call
199 // occurs between the
200 // setTerminationEnable(false) and the
201 // mutex lock in safeLock() called
203 qDebug(">>> %c <<<\n", x++);
204 syncCondition.wakeAll();
205 qDebug(">>> %c <<<\n", x++);
207 qDebug(">>> %c <<<\n", x++);
208 QWidget::closeEvent(ev);
209 qDebug(">>> %c <<<\n", x++);
211 qDebug(">>> %c <<<\n", x++);
212 qDebug(">>>CLOSED<<<\n");
215 void DrawingWindow::customEvent(QEvent *)
218 qApp->sendPostedEvents(this, QEvent::UpdateLater);
219 qApp->sendPostedEvents(this, QEvent::UpdateRequest);
220 qApp->sendPostedEvents(this, QEvent::Paint);
221 qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
222 QEventLoop::ExcludeSocketNotifiers |
223 QEventLoop::DeferredDeletion |
224 QEventLoop::X11ExcludeTimers);
228 syncCondition.wakeAll();
232 void DrawingWindow::keyPressEvent(QKeyEvent *ev)
247 void DrawingWindow::paintEvent(QPaintEvent *ev)
249 QPainter widgetPainter(this);
251 QImage imageCopy(*image);
253 QRect rect = ev->rect();
254 widgetPainter.drawImage(rect, imageCopy, rect);
257 void DrawingWindow::showEvent(QShowEvent *ev)
259 timer.start(paintInterval, this);
260 thread->start_once(QThread::IdlePriority);
261 QWidget::showEvent(ev);
264 void DrawingWindow::timerEvent(QTimerEvent *ev)
266 if (ev->timerId() == timer.timerId()) {
268 timer.start(paintInterval, this);
270 QWidget::timerEvent(ev);
274 //--- DrawingWindow (private methods) ----------------------------------
276 void DrawingWindow::initialize(DrawingWindow::ThreadFunction f)
278 terminateThread = false;
280 image = new QImage(width, height, QImage::Format_RGB32);
281 painter = new QPainter(image);
282 thread = new DrawingThread(*this, f);
284 setFocusPolicy(Qt::StrongFocus);
285 setFixedSize(image->size());
286 setAttribute(Qt::WA_OpaquePaintEvent);
297 void DrawingWindow::applyColor()
299 QPen pen(painter->pen());
300 pen.setColor(fgColor);
301 painter->setPen(pen);
305 void DrawingWindow::safeLock(QMutex &mutex)
307 if (lockCount++ == 0)
308 thread->setTerminationEnabled(false);
313 void DrawingWindow::safeUnlock(QMutex &mutex)
316 if (--lockCount == 0)
317 thread->setTerminationEnabled(true);
321 void DrawingWindow::dirty()
324 dirtyRect = image->rect();
328 void DrawingWindow::dirty(int x, int y)
330 dirty(QRect(x, y, 1, 1));
334 void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
337 r.setCoords(x1, y1, x2, y2);
338 dirty(r.normalized());
341 void DrawingWindow::dirty(const QRect &rect)
351 void DrawingWindow::mayUpdate()
354 bool dirty = dirtyFlag;
355 QRect rect = dirtyRect;
362 //--- DrawingThread ----------------------------------------------------
364 DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
367 , started_once(false)
371 void DrawingThread::start_once(Priority priority)
379 void DrawingThread::run()
381 threadFunction(drawingWindow);