#include "DrawingWindow.h"
-#include <QPainter>
#include <QPaintEvent>
+#include <QThread>
+#include <QTimerEvent>
-#include <iostream>
+class DrawingWindow::DrawingThread: public QThread {
+public:
+ DrawingThread(DrawingWindow &w, ThreadFunction f)
+ : drawingWindow(w)
+ , threadFunction(f)
+ {
+ }
+
+ void run()
+ {
+ exit(threadFunction(drawingWindow));
+ }
-DrawingWindow::DrawingWindow(DrawingArea &a)
+private:
+ DrawingWindow &drawingWindow;
+ ThreadFunction threadFunction;
+
+};
+
+DrawingWindow::DrawingWindow(ThreadFunction fun, int width, int height)
: QWidget()
- , drawingArea(a)
- , pixmap(a.size())
{
- initialize();
+ initialize(fun, width, height);
}
-DrawingWindow::DrawingWindow(QWidget *parent, DrawingArea &a)
+DrawingWindow::DrawingWindow(QWidget *parent,
+ ThreadFunction fun, int width, int height)
: QWidget(parent)
- , drawingArea(a)
- , pixmap(a.size())
{
- initialize();
+ initialize(fun, width, height);
}
DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
- DrawingArea &a)
+ ThreadFunction fun, int width, int height)
: QWidget(parent, flags)
- , drawingArea(a)
- , pixmap(a.size())
{
- initialize();
+ initialize(fun, width, height);
+}
+
+void DrawingWindow::initialize(ThreadFunction fun, int width, int height)
+{
+ image = new QImage(width, height, QImage::Format_RGB32);
+ image->fill(QColor(Qt::white).rgb());
+
+ painter = new QPainter(image);
+
+#ifdef USE_PIXMAP_CACHE
+ pixmap = new QPixmap(image->size());
+ QPainter pixmapPainter(pixmap);
+ pixmapPainter.drawImage(0, 0, *image);
+#endif
+
+ dirtyFlag = false;
+
+ setFocusPolicy(Qt::StrongFocus);
+ setFixedSize(image->size());
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setFocus();
+ timer.start(paintInterval, this);
+
+ thread = new DrawingThread(*this, fun);
+ thread_started = false;
+}
+
+DrawingWindow::~DrawingWindow()
+{
+ delete thread;
+#ifdef USE_PIXMAP_CACHE
+ delete pixmap;
+#endif
+ delete painter;
+ delete image;
+}
+
+void DrawingWindow::setColor(const QColor &color)
+{
+ QPen pen(painter->pen());
+ pen.setColor(color);
+ painter->setPen(pen);
+}
+
+void DrawingWindow::setColor(float red, float green, float blue)
+{
+ QColor color;
+ color.setRgbF(red, green, blue);
+ this->setColor(color);
+}
+
+void DrawingWindow::drawPoint(int x, int y)
+{
+ lock();
+ painter->drawPoint(x, y);
+ setDirtyRect(x, y);
+ unlock();
+}
+
+void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
+{
+ lock();
+ painter->drawLine(x1, y1, x2, y2);
+ setDirtyRect(x1, y1, x2, y2);
+ unlock();
}
void DrawingWindow::paintEvent(QPaintEvent *ev)
{
+ QPainter widgetPainter(this);
QRect rect = ev->rect();
- drawingArea.lock();
- if (drawingArea.isDirty()) {
- QPainter pixmapPainter(&pixmap);
- pixmapPainter.drawImage(drawingArea.getDirtyRect(),
- drawingArea.getImage(),
- drawingArea.getDirtyRect());
- drawingArea.setClean();
- rect |= drawingArea.getDirtyRect();
+#ifdef USE_PIXMAP_CACHE
+ widgetPainter.drawPixmap(rect, *pixmap, rect);
+#else
+ lock();
+ widgetPainter.drawImage(rect, *image, rect);
+ unlock();
+#endif
+}
+
+void DrawingWindow::showEvent(QShowEvent *ev)
+{
+ if (!thread_started) {
+ thread->start();
+ thread_started = true;
}
- drawingArea.unlock();
- QPainter painter(this);
- painter.drawPixmap(0, 0, pixmap);
+ QWidget::showEvent(ev);
}
void DrawingWindow::timerEvent(QTimerEvent *ev)
{
if (ev->timerId() == timer.timerId()) {
- update();
+ lock();
+ if (dirtyFlag) {
+#ifdef USE_PIXMAP_CACHE
+ QPainter pixmapPainter(pixmap);
+ pixmapPainter.drawImage(dirtyRect, *image, dirtyRect);
+#endif
+ dirtyFlag = false;
+ update(dirtyRect);
+ timer.start(paintInterval, this);
+ }
+ unlock();
} else {
QWidget::timerEvent(ev);
}
}
-void DrawingWindow::initialize()
+void DrawingWindow::setDirtyRect()
{
- setFocusPolicy(Qt::StrongFocus);
- setFixedSize(drawingArea.getImage().size());
- setAttribute(Qt::WA_OpaquePaintEvent);
- timer.start(50, this);
+ setDirtyRect(QRect(0, 0, width(), height()));
+}
+
+void DrawingWindow::setDirtyRect(int x, int y)
+{
+ setDirtyRect(QRect(x, y, 1, 1));
+}
+
+void DrawingWindow::setDirtyRect(int x1, int y1, int x2, int y2)
+{
+ QRect r;
+ r.setCoords(x1, y1, x2, y2);
+ setDirtyRect(r.normalized());
+}
+
+void DrawingWindow::setDirtyRect(const QRect &rect)
+{
+ if (dirtyFlag) {
+ dirtyRect |= rect;
+ } else {
+ dirtyFlag = true;
+ dirtyRect = rect;
+ }
}