Logo AND Algorithmique Numérique Distribuée

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