Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
9a8d501413159c1a26b999468a4529e19acebd13
[graphlib.git] / DrawingWindow.cpp
1 #include "DrawingWindow.h"
2 #include <QPaintEvent>
3 #include <QThread>
4 #include <QTimerEvent>
5
6 class DrawingWindow::DrawingThread: public QThread {
7 public:
8     DrawingThread(DrawingWindow &w, ThreadFunction f)
9         : drawingWindow(w)
10         , threadFunction(f)
11     {
12     }
13
14     void run()
15     {
16         exit(threadFunction(drawingWindow));
17     }
18
19 private:
20     DrawingWindow &drawingWindow;
21     ThreadFunction threadFunction;
22
23 };
24
25 DrawingWindow::DrawingWindow(ThreadFunction fun, int width, int height)
26     : QWidget()
27 {
28     initialize(fun, width, height);
29 }
30
31 DrawingWindow::DrawingWindow(QWidget *parent,
32                              ThreadFunction fun, int width, int height)
33     : QWidget(parent)
34 {
35     initialize(fun, width, height);
36 }
37
38 DrawingWindow::DrawingWindow(QWidget *parent, Qt::WindowFlags flags,
39                              ThreadFunction fun, int width, int height)
40     : QWidget(parent, flags)
41 {
42     initialize(fun, width, height);
43 }
44
45 void DrawingWindow::initialize(ThreadFunction fun, int width, int height)
46 {
47     image = new QImage(width, height, QImage::Format_RGB32);
48     image->fill(QColor(Qt::white).rgb());
49
50     painter = new QPainter(image);
51
52 #ifdef USE_PIXMAP_CACHE
53     pixmap = new QPixmap(image->size());
54     QPainter pixmapPainter(pixmap);
55     pixmapPainter.drawImage(0, 0, *image);
56 #endif
57
58     dirtyFlag = false;
59
60     setFocusPolicy(Qt::StrongFocus);
61     setFixedSize(image->size());
62     setAttribute(Qt::WA_OpaquePaintEvent);
63     setFocus();
64     timer.start(paintInterval, this);
65
66     thread = new DrawingThread(*this, fun);
67     thread_started = false;
68 }
69
70 DrawingWindow::~DrawingWindow()
71 {
72     delete thread;
73 #ifdef USE_PIXMAP_CACHE
74     delete pixmap;
75 #endif
76     delete painter;
77     delete image;
78 }
79
80 void DrawingWindow::setColor(const QColor &color)
81 {
82     QPen pen(painter->pen());
83     pen.setColor(color);
84     painter->setPen(pen);
85 }
86
87 void DrawingWindow::setColor(float red, float green, float blue)
88 {
89     QColor color;
90     color.setRgbF(red, green, blue);
91     this->setColor(color);
92 }
93
94 void DrawingWindow::drawPoint(int x, int y)
95 {
96     lock();
97     painter->drawPoint(x, y);
98     setDirtyRect(x, y);
99     unlock();
100 }
101
102 void DrawingWindow::drawLine(int x1, int y1, int x2, int y2)
103 {
104     lock();
105     painter->drawLine(x1, y1, x2, y2);
106     setDirtyRect(x1, y1, x2, y2);
107     unlock();
108 }
109
110 void DrawingWindow::paintEvent(QPaintEvent *ev)
111 {
112     QPainter widgetPainter(this);
113     QRect rect = ev->rect();
114 #ifdef USE_PIXMAP_CACHE
115     widgetPainter.drawPixmap(rect, *pixmap, rect);
116 #else
117     lock();
118     widgetPainter.drawImage(rect, *image, rect);
119     unlock();
120 #endif
121 }
122
123 void DrawingWindow::showEvent(QShowEvent *ev)
124 {
125     if (!thread_started) {
126         thread->start();
127         thread_started = true;
128     }
129     QWidget::showEvent(ev);
130 }
131
132 void DrawingWindow::timerEvent(QTimerEvent *ev)
133 {
134     if (ev->timerId() == timer.timerId()) {
135         lock();
136         if (dirtyFlag) {
137 #ifdef USE_PIXMAP_CACHE
138             QPainter pixmapPainter(pixmap);
139             pixmapPainter.drawImage(dirtyRect, *image, dirtyRect);
140 #endif
141             dirtyFlag = false;
142             update(dirtyRect);
143             timer.start(paintInterval, this);
144         }
145         unlock();
146     } else {
147         QWidget::timerEvent(ev);
148     }
149 }
150
151 void DrawingWindow::setDirtyRect()
152 {
153     setDirtyRect(QRect(0, 0, width(), height()));
154 }
155
156 void DrawingWindow::setDirtyRect(int x, int y)
157 {
158     setDirtyRect(QRect(x, y, 1, 1));
159 }
160
161 void DrawingWindow::setDirtyRect(int x1, int y1, int x2, int y2)
162 {
163     QRect r;
164     r.setCoords(x1, y1, x2, y2);
165     setDirtyRect(r.normalized());
166 }
167
168 void DrawingWindow::setDirtyRect(const QRect &rect)
169 {
170     if (dirtyFlag) {
171         dirtyRect |= rect;
172     } else {
173         dirtyFlag = true;
174         dirtyRect = rect;
175     }
176 }