+/*
+ * Copyright (c) 2007-2010, Arnaud Giersch <arnaud.giersch@iut-bm.univ-fcomte.fr>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
#include "DrawingWindow.h"
#include <QApplication>
#include <QPaintEvent>
#include <QThread>
#include <QTimerEvent>
-/*! Classe de thread.
+/*! \class DrawingWindow
+ * \brief Fenêtre de dessin.
+ *
+ * \author Arnaud Giersch <arnaud.giersch@iut-bm.univ-fcomte.fr>
+ * \date 2007-2010
+ *
+ * Cette classe décrit un widget Qt permettant d'écrire des
+ * applications graphiques simples. Pour cela, il faut définir une
+ * fonction de dessin. Cette fonction ne retourne rien et prend comme
+ * unique paramètre une référence vers un objet de class
+ * DrawingWindow.
+ *
+ * La fonction devra ensuite être passée en paramètre pour les
+ * constructeurs de la classe, ainsi que les dimension requises pour
+ * la fenêtre graphique. Le programme est ensuite compilé comme
+ * n'importe quel programme Qt.
+ *
+ * Concrètement, la fonction sera exécutée dans un nouveau thread,
+ * tandis que le thread principal s'occupera de la gestion des
+ * évènements et du rendu dans la fenêtre.
+ *
+ * <b>NB.</b> Pour toutes les méthodes de dessin, le coin en haut à gauche
+ * de la fenêtre a les coordonnées (0, 0). Le coin en bas à droite de
+ * la fenêtre a les coordonnées (largeur - 1, hauteur - 1), si la
+ * fenêtre est de dimension largeur × hauteur.
+ *
+ * Un appui sur la touche <Esc> provoque la fermeture de la fenêtre.
+ * Comme pour la plupart des applications, il est également possible
+ * de fermer la fenêtre via le gestionnaire de fenêtres.
+ *
+ * Il est possible, dans une application, d'ouvrir plusieurs fenêtres,
+ * avec des fonctions de dessin éventuellement différentes.
+ * L'application se terminera normalement lorsque la dernière fenêtre
+ * sera fermée.
+ */
+
+/*! \example hello.cpp
+ *
+ * Voir le code source à la fin de la page. Pour compiler et exécuter
+ * ce programme, il faut :
+ *
+ * <b>1. Créer le fichier \c hello.pro</b>
+ *
+ * Pour simplifier, ce fichier contient la liste des fichiers sources
+ * composant le programme.
+ *
+ * \include hello.pro
+ *
+ * <b>2. Créer le fichier \c Makefile avec la commande :</b>
+ *
+ * \verbatim qmake-qt4 hello.pro \endverbatim
+ * ou tout simplement :
+ * \verbatim qmake-qt4 \endverbatim
+ *
+ * <b>3. Compiler le programme avec la commande :</b>
+ *
+ * \verbatim make hello \endverbatim
+ * ou tout simplement :
+ * \verbatim make \endverbatim
+ *
+ * <b>4. Exécuter le programme avec la commande :</b>
+ *
+ * \verbatim ./hello \endverbatim
+ *
+ * <b>Code source de l'exemple</b>
+ */
+
+/*! \example exemple.cpp
+ *
+ * Un exemple un peu plus sophistiqué.
*/
+
+//! Classe de thread.
class DrawingThread: public QThread {
public:
DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f);
enum UserEvents {
SyncRequest = QEvent::User, //!< Demande de synchronisation.
- CloseRequest, //!< Demande de fermeture de la fenêtre.
- DrawTextRequest, //!< Demande d'écriture de texte.
+ CloseRequest, //!< Demande de fermeture de la fenêtre.
+ DrawTextRequest, //!< Demande d'écriture de texte.
};
-/*! Demande de synchronisation.
- */
+//! Demande de synchronisation.
class SyncRequestEvent: public QEvent {
public:
SyncRequestEvent(): QEvent(static_cast<QEvent::Type>(SyncRequest))
{ }
};
-/*! Demande de fermeture de fenêtre.
- */
+//! Demande de fermeture de fenêtre.
class CloseRequestEvent: public QEvent {
public:
CloseRequestEvent(): QEvent(static_cast<QEvent::Type>(CloseRequest))
{ }
};
-/*! Demande de tracé de texte.
- */
+//! Demande de tracé de texte.
class DrawTextEvent: public QEvent {
public:
const int x;
const int y;
const char *text;
const int flags;
- DrawTextEvent(int x_, int y_, const char* text_, int flags_)
+ DrawTextEvent(int x_, int y_, const char *text_, int flags_)
: QEvent(static_cast<QEvent::Type>(DrawTextRequest))
, x(x_), y(y_), text(text_), flags(flags_)
{ }
//--- DrawingWindow ----------------------------------------------------
-/*! Constructeur.
- *
- * Construit une nouvelle fenêtre de dessin avec les dimensions
- * passées en paramètres. La fonction fun sera exécutée dans un
+/*! \file DrawingWindow.h
+ * \brief Classe DrawingWindow.
+ */
+
+/*! \typedef DrawingWindow::ThreadFunction
+ * \brief Type de la fonction de dessin, passée en paramètre de construction.
+ */
+/*! \var DrawingWindow::DEFAULT_WIDTH
+ * \brief Largeur par défaut de la fenêtre.
+ */
+/*! \var DrawingWindow::DEFAULT_HEIGHT
+ * \brief Hauteur par défaut de la fenêtre.
+ */
+/*! \var DrawingWindow::width
+ * \brief Largeur de la fenêtre.
+ */
+/*! \var DrawingWindow::height
+ * \brief Hauteur de la fenêtre.
+ */
+/*! \var DrawingWindow::paintInterval
+ * \brief Intervalle de temps entre deux rendus (ms).
+ */
+
+//! Constructeur.
+/*!
+ * Construit une nouvelle fenêtre de dessin avec les dimensions
+ * passées en paramètres. La fonction fun sera exécutée dans un
* nouveau thread.
*
* \param fun fonction de dessin
- * \param width_ largeur de la fenêtre
- * \param height_ hauteur de la fenêtre
+ * \param width_ largeur de la fenêtre
+ * \param height_ hauteur de la fenêtre
*
* \see QWidget
*/
initialize(fun);
}
-/*! Constructeur.
- *
- * Construit un nouveau widget de dessin avec les dimensions passées
- * en paramètres. La fonction fun sera exécutée dans un nouveau
+//! Constructeur.
+/*!
+ * Construit un nouveau widget de dessin avec les dimensions passées
+ * en paramètres. La fonction fun sera exécutée dans un nouveau
* thread.
*
* \param parent widget parent
* \param fun fonction de dessin
- * \param width_ largeur de la fenêtre
- * \param height_ hauteur de la fenêtre
+ * \param width_ largeur de la fenêtre
+ * \param height_ hauteur de la fenêtre
*
* \see QWidget
*/
initialize(fun);
}
-/*! Constructeur.
- *
- * Construit un nouveau widget de dessin avec les dimensions passées
- * en paramètres. La fonction fun sera exécutée dans un nouveau
+//! Constructeur.
+/*!
+ * Construit un nouveau widget de dessin avec les dimensions passées
+ * en paramètres. La fonction fun sera exécutée dans un nouveau
* thread.
*
* \param parent widget parent
- * \param flags flags passés au constructeur de QWidget
+ * \param flags flags passés au constructeur de QWidget
* \param fun fonction de dessin
- * \param width_ largeur de la fenêtre
- * \param height_ hauteur de la fenêtre
+ * \param width_ largeur de la fenêtre
+ * \param height_ hauteur de la fenêtre
*
* \see QWidget
*/
initialize(fun);
}
-/*! Destructeur.
- */
+//! Destructeur.
DrawingWindow::~DrawingWindow()
{
delete thread;
delete image;
}
-/*! Change la couleur de dessin.
- *
- * La couleur est un entier, tel que retourné par getPointColor.
+//! Change la couleur de dessin.
+/*!
+ * La couleur est un entier, tel que retourné par getPointColor.
* Normalement de la forme #00RRGGBB.
*
* \param color couleur
setColor(QColor::fromRgb(color));
}
-/*! Change la couleur de dessin.
- *
+//! Change la couleur de dessin.
+/*!
* Le nom de couleur est de la forme "black", "white", "red", "blue", ...
*
* \param name nom de couleur
setColor(QColor(name));
}
-/*! Change la couleur de dessin.
- *
- * Les composantes de rouge, vert et bleu de la couleur doivent être
- * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient
- * du noir; si les trois composantes sont à 1, on obtient du blanc.
+//! Change la couleur de dessin.
+/*!
+ * Les composantes de rouge, vert et bleu de la couleur doivent être
+ * compris entre 0 et 1. Si le trois composantes sont à 0, on obtient
+ * du noir; si les trois composantes sont à 1, on obtient du blanc.
*
* \param red composante de rouge
* \param green composante de vert
setColor(QColor::fromRgbF(red, green, blue));
}
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
* \param color couleur
*
* \see setBgColor(const char *), setBgColor(float, float, float),
setBgColor(QColor::fromRgb(color));
}
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
* \param name nom de couleur
*
* \see setBgColor(unsigned int), setBgColor(float, float, float),
setBgColor(QColor(name));
}
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
* \param red composante de rouge
* \param green composante de vert
* \param blue composante de bleu
setBgColor(QColor::fromRgbF(red, green, blue));
}
-/*! Efface la fenêtre.
+//! Change l'épaisseur du pinceau
+/*!
+ * Le pinceau à une épaisseur de 1 par défaut.
*
- * La fenêtre est effacée avec la couleur de fond courante.
+ * \param width épaisseur du pinceau
+ */
+void DrawingWindow::setPenWidth(int width)
+{
+ QPen pen(painter->pen());
+ pen.setWidth(width);
+ painter->setPen(pen);
+}
+
+//! Retourne la fonte courante utilisée pour dessiner du texte.
+/*!
+ * \see QFont, setFont
+ */
+const QFont &DrawingWindow::getFont() const
+{
+ return painter->font();
+}
+
+//! Applique une nouvelle font pour dessiner du texte.
+/*!
+ * \see QFont, getFont
+ */
+void DrawingWindow::setFont(const QFont &font)
+{
+ painter->setFont(font);
+}
+
+//! Active ou non l'antialiasing.
+/*!
+ * Permet de lisser le dessin.
+ * Fonctionnalité désactivée par défaut.
+ *
+ * \param state état de l'antialiasing
+ *
+ * \bug expérimental
+ */
+void DrawingWindow::setAntialiasing(bool state)
+{
+ painter->setRenderHint(QPainter::Antialiasing, state);
+}
+
+//! Efface la fenêtre.
+/*!
+ * La fenêtre est effacée avec la couleur de fond courante.
*
* \see setBgColor
*/
safeUnlock(imageMutex);
}
-/*! Dessine un point.
- *
- * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
+//! Dessine un point.
+/*!
+ * Dessine un point (pixel) aux coordonnées (x, y), avec la couleur de
* dessin courante.
*
- * \param x, y coordonnées du point
+ * \param x, y coordonnées du point
*
* \see setColor
*/
safeUnlock(imageMutex);
}
-/*! Dessine un segment.
- *
- * Dessine un segement de droite entre les coordonnées (x1, y1) et
+//! Dessine un segment.
+/*!
+ * Dessine un segement de droite entre les coordonnées (x1, y1) et
* (x2, y2), avec la couleur de dessin courante.
*
- * \param x1, y1 coordonnées d'une extrémité du segment
- * \param x2, y2 coordonnées de l'autre extrémité du segment
+ * \param x1, y1 coordonnées d'une extrémité du segment
+ * \param x2, y2 coordonnées de l'autre extrémité du segment
*
* \see setColor
*/
safeUnlock(imageMutex);
}
-/*! Dessine un rectangle.
- *
- * Dessine le rectangle parallèle aux axes et défini par les
- * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
+//! Dessine un rectangle.
+/*!
+ * Dessine le rectangle parallèle aux axes et défini par les
+ * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
* la couleur de dessin courante.
*
- * \param x1, y1 coordonnées d'un sommet du rectangle
- * \param x2, y2 coordonnées du sommet opposé du rectangle
+ * \param x1, y1 coordonnées d'un sommet du rectangle
+ * \param x2, y2 coordonnées du sommet opposé du rectangle
*
* \see fillRect, setColor
*/
safeUnlock(imageMutex);
}
-/*! Dessine un rectangle plein.
- *
- * Dessine le rectangle plein parallèle aux axes et défini par les
- * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
+//! Dessine un rectangle plein.
+/*!
+ * Dessine le rectangle plein parallèle aux axes et défini par les
+ * coordonnées de deux sommets opposés (x1, y1) et (x2, y2). Utilise
* la couleur de dessin courante.
*
- * \param x1, y1 coordonnées d'un sommet du rectangle
- * \param x2, y2 coordonnées du sommet opposé du rectangle
+ * \param x1, y1 coordonnées d'un sommet du rectangle
+ * \param x2, y2 coordonnées du sommet opposé du rectangle
*
* \see drawRect, setColor
*/
painter->setBrush(Qt::NoBrush);
}
-/*! Dessine un cercle.
- *
+//! Dessine un cercle.
+/*!
* Dessine un cercle de centre (x, y) et de rayon r. Utilise la
* couleur de dessin courante.
*
- * \param x, y coordonnées du centre du cercle
+ * \param x, y coordonnées du centre du cercle
* \param r rayon du cercle
*
* \see fillCircle, setColor
safeUnlock(imageMutex);
}
-/*! Dessine un disque.
- *
+//! Dessine un disque.
+/*!
* Dessine un disque (cercle plein) de centre (x, y) et de rayon r.
* Utilise la couleur de dessin courante.
*
- * \param x, y coordonnées du centre du disque
+ * \param x, y coordonnées du centre du disque
* \param r rayon du disque
*
* \see drawCircle, setColor
painter->setBrush(Qt::NoBrush);
}
-/*! Écrit du texte.
+//! Dessine un triangle.
+/*!
+ * Dessine un triangle défini par les coordonnées de ses sommets:
+ * (x1, y1), (x2, y2) et (x3, y3). Utilise la couleur de dessin
+ * courante.
*
- * Écrit le texte text, aux coordonnées (x, y) et avec les paramètres
- * d'alignement flags. Le texte est écrit avec la couleur de dessin
+ * \param x1, y1 coordonnées du premier sommet du triangle
+ * \param x2, y2 coordonnées du deuxième sommet du triangle
+ * \param x3, y3 coordonnées du troisième sommet du triangle
+ *
+ * \see fillTriangle, setColor
+ */
+void DrawingWindow::drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3)
+{
+ QPolygon poly(3);
+ poly.putPoints(0, 3, x1, y1, x2, y2, x3, y3);
+ safeLock(imageMutex);
+ painter->drawConvexPolygon(poly);
+ dirty(poly.boundingRect());
+ safeUnlock(imageMutex);
+}
+
+//! Dessine un triangle plein.
+/*!
+ * Dessine un triangle plein défini par les coordonnées de ses
+ * sommets: (x1, y1), (x2, y2) et (x3, y3). Utilise la couleur de
+ * dessin courante.
+ *
+ * \param x1, y1 coordonnées du premier sommet du triangle
+ * \param x2, y2 coordonnées du deuxième sommet du triangle
+ * \param x3, y3 coordonnées du troisième sommet du triangle
+ *
+ * \see drawTriangle, setColor
+ */
+void DrawingWindow::fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3)
+{
+ painter->setBrush(getColor());
+ drawTriangle(x1, y1, x2, y2, x3, y3);
+ painter->setBrush(Qt::NoBrush);
+}
+
+//! Écrit du texte.
+/*!
+ * Écrit le texte text, aux coordonnées (x, y) et avec les paramètres
+ * d'alignement flags. Le texte est écrit avec la couleur de dessin
* courante. Les flags sont une combinaison (ou binaire) de
* Qt::AlignLeft, Qt::AligneRight, Qt::AlignHCenter, Qt::AlignTop,
- * Qt::AlignBottom, Qt::AlignVCenter, Qt::AlignCenter. Par défaut, le
- * texte est aligné en haut à gauche.
+ * Qt::AlignBottom, Qt::AlignVCenter, Qt::AlignCenter. Par défaut, le
+ * texte est aligné en haut à gauche.
*
- * \param x, y coordonnées du texte
- * \param text texte à écrire
- * \param flags paramètres d'alignement
+ * \param x, y coordonnées du texte
+ * \param text texte à écrire
+ * \param flags paramètres d'alignement
*
+ * \see drawText(int, int, const std::string &, int)
* \see drawTextBg, setColor
* \see QPainter::drawText
*/
safeUnlock(syncMutex);
}
-/*! Écrit du texte sur fond coloré.
- *
- * Écrit du texte comme drawText, mais l'arrière-plan est coloré avec
+//! Écrit du texte.
+/*!
+ * \see drawText(int, int, const char *, int)
+ */
+void DrawingWindow::drawText(int x, int y, const std::string &text, int flags)
+{
+ drawText(x, y, text.c_str(), flags);
+}
+
+//! Écrit du texte sur fond coloré.
+/*!
+ * Écrit du texte comme drawText, mais l'arrière-plan est coloré avec
* la couleur de fond courante.
*
- * \param x, y coordonnées du texte
- * \param text texte à écrire
- * \param flags paramètres d'alignement
+ * \param x, y coordonnées du texte
+ * \param text texte à écrire
+ * \param flags paramètres d'alignement
*
+ * \see drawTextBg(int, int, const std::string &, int)
* \see drawText, setColor, setColorBg
*/
void DrawingWindow::drawTextBg(int x, int y, const char *text, int flags)
painter->setBackgroundMode(Qt::TransparentMode);
}
+//! Écrit du texte sur fond coloré.
+/*!
+ * \see drawTextBg(int, int, const char *, int)
+ */
+void DrawingWindow::drawTextBg(int x, int y, const std::string &text, int flags)
+{
+ drawTextBg(x, y, text.c_str(), flags);
+}
-/*! Retourne la couleur d'un pixel.
- *
- * Retourne la couleur du pixel de coordonnées (x, y). La valeur
- * retournée peut servir de paramètres à setColor(unsigned int) ou
+//! Retourne la couleur d'un pixel.
+/*!
+ * Retourne la couleur du pixel de coordonnées (x, y). La valeur
+ * retournée peut servir de paramètres à setColor(unsigned int) ou
* setBgColor(unsigned int).
*
- * \param x, y coordonnées du pixel
+ * \param x, y coordonnées du pixel
* \return couleur du pixel
*
* \see setColor(unsigned int), setBgColor(unsigned int)
*/
-unsigned int DrawingWindow::getPointColor(int x, int y)
+unsigned int DrawingWindow::getPointColor(int x, int y) const
{
return image->pixel(x, y);
}
-/*! Synchronise le contenu de la fenêtre.
- *
- * Pour des raisons d'efficacités, le résultat des fonctions de dessin
- * n'est pas affiché immédiatement. L'appel à sync permet de
- * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque
- * l'exécution du programme jusqu'à ce que le contenu de la fenêtre
- * soit à jour.
- *
- * \param time durée maximale de l'attente
- * \return true si la fenêtre a pu être synchronisée
+//! Attend l'appui sur un des boutons de la souris.
+/*!
+ * Attend l'appui sur un des boutons de la souris. Retourne le bouton
+ * qui a été pressé et les coordonnées du pointeur de souris à ce
+ * moment-là.
+ *
+ * \param x, y coordonnées du pointeur de souris
+ * \param button numéro du bouton qui a été pressé
+ * (1: gauche, 2: droit, 3: milieu, 0 sinon)
+ * \param time durée maximale de l'attente
+ * \return true si un bouton a été pressé
+ *
+ * \bug expérimental
+ */
+bool DrawingWindow::waitMousePress(int &x, int &y, int &button,
+ unsigned long time)
+{
+ bool pressed;
+ safeLock(mouseMutex);
+ if (terminateThread) {
+ pressed = false;
+ } else {
+ pressed = mouseCondition.wait(&mouseMutex, time);
+ if (pressed) {
+ x = mousePos.x();
+ y = mousePos.y();
+ if (mouseButton & Qt::LeftButton)
+ button = 1;
+ else if (mouseButton & Qt::RightButton)
+ button = 2;
+ else if (mouseButton & Qt::MidButton)
+ button = 3;
+ else
+ button = 0;
+ }
+ }
+ safeUnlock(mouseMutex);
+ return pressed;
+}
+
+//! Synchronise le contenu de la fenêtre.
+/*!
+ * Pour des raisons d'efficacités, le résultat des fonctions de dessin
+ * n'est pas affiché immédiatement. L'appel à sync permet de
+ * synchroniser le contenu de la fenêtre. Autrement dit, cela bloque
+ * l'exécution du programme jusqu'à ce que le contenu de la fenêtre
+ * soit à jour.
+ *
+ * \param time durée maximale de l'attente
+ * \return true si la fenêtre a pu être synchronisée
*/
bool DrawingWindow::sync(unsigned long time)
{
return synced;
}
-/*! Ferme la fenêtre graphique.
- */
+//! Ferme la fenêtre graphique.
void DrawingWindow::closeGraph()
{
qApp->postEvent(this, new CloseRequestEvent());
}
-/*! Suspend l'exécution pendant un certain temps.
- *
+//! Suspend l'exécution pendant un certain temps.
+/*!
* \param secs temps d'attente en seconde
*/
void DrawingWindow::sleep(unsigned long secs)
DrawingThread::sleep(secs);
}
-/*! Suspend l'exécution pendant un certain temps.
- *
+//! Suspend l'exécution pendant un certain temps.
+/*!
* \param msecs temps d'attente en millisecondes
*/
void DrawingWindow::msleep(unsigned long msecs)
DrawingThread::msleep(msecs);
}
-/*! Suspend l'exécution pendant un certain temps.
- *
+//! Suspend l'exécution pendant un certain temps.
+/*!
* \param usecs temps d'attente en microsecondes
*/
void DrawingWindow::usleep(unsigned long usecs)
DrawingThread::usleep(usecs);
}
-/*! \see QWidget
+/*!
+ * \see QWidget
*/
void DrawingWindow::closeEvent(QCloseEvent *ev)
{
timer.stop();
thread->terminate();
syncMutex.lock();
+ mouseMutex.lock();
terminateThread = true; // this flag is needed for the case
// where the following wakeAll() call
// occurs between the
// mutex lock in safeLock() called
// from sync()
syncCondition.wakeAll();
+ mouseCondition.wakeAll();
+ mouseMutex.unlock();
syncMutex.unlock();
QWidget::closeEvent(ev);
thread->wait();
}
-/*! \see QWidget
+/*!
+ * \see QWidget
*/
void DrawingWindow::customEvent(QEvent *ev)
{
close();
break;
case DrawTextRequest:
- DrawTextEvent* tev = dynamic_cast<DrawTextEvent *>(ev);
+ DrawTextEvent *tev = dynamic_cast<DrawTextEvent *>(ev);
realDrawText(tev->x, tev->y, tev->text, tev->flags);
break;
}
}
-/*! \see QWidget
+/*!
+ * \see QWidget
+ *
+ * \bug expérimental
+ */
+void DrawingWindow::mousePressEvent(QMouseEvent *ev)
+{
+ mouseMutex.lock();
+ mousePos = ev->pos();
+ mouseButton = ev->button();
+ ev->accept();
+ mouseCondition.wakeAll();
+ mouseMutex.unlock();
+}
+
+/*!
+ * \see QWidget
*/
void DrawingWindow::keyPressEvent(QKeyEvent *ev)
{
ev->accept();
}
-/*! \see QWidget
+/*!
+ * \see QWidget
*/
void DrawingWindow::paintEvent(QPaintEvent *ev)
{
widgetPainter.drawImage(rect, imageCopy, rect);
}
-/*! \see QWidget
+/*!
+ * \see QWidget
*/
void DrawingWindow::showEvent(QShowEvent *ev)
{
thread->start_once(QThread::IdlePriority);
}
-/*! \see QWidget
+/*!
+ * \see QWidget
*/
void DrawingWindow::timerEvent(QTimerEvent *ev)
{
//--- DrawingWindow (private methods) ----------------------------------
-/*! Fonction d'initialisation.
- *
- * Fonction appelée par les différents constructeurs.
+//! Fonction d'initialisation.
+/*!
+ * Fonction appelée par les différents constructeurs.
*
* \param fun fonction de dessin
*/
dirtyFlag = false;
}
-/*! Change la couleur de dessin.
- *
+//! Change la couleur de dessin.
+/*!
* \param color couleur
*/
inline
-void DrawingWindow::setColor(const QColor& color)
+void DrawingWindow::setColor(const QColor &color)
{
QPen pen(painter->pen());
pen.setColor(color);
painter->setPen(pen);
}
-/*! Change la couleur de fond.
- *
+//! Change la couleur de fond.
+/*!
* \param color couleur
*/
inline
-void DrawingWindow::setBgColor(const QColor& color)
+void DrawingWindow::setBgColor(const QColor &color)
{
painter->setBackground(color);
}
-/*! Retourne la couleur de dessin courante.
- *
+//! Retourne la couleur de dessin courante.
+/*!
* \return couleur de dessin courante
*/
inline
return painter->pen().color();
}
-/*! Retourne la couleur de fond courante.
- *
+//! Retourne la couleur de fond courante.
+/*!
* \return couleur de fond courante
*/
inline
return painter->background().color();
}
-/*! Verrouille un mutex.
+//! Verrouille un mutex.
+/*!
+ * S'assure que le thread courant ne peut pas être terminé s'il
+ * détient un mutex. Pendant de safeUnlock.
*
- * S'assure que le thread courant ne peut pas être terminé s'il
- * détient un mutex. Pendant de safeUnlock.
- *
- * \param mutex le mutex à verrouiller
+ * \param mutex le mutex à verrouiller
*
* \see safeUnlock
*/
mutex.lock();
}
-/*! Déverrouille un mutex.
- *
- * S'assure que le thread courant ne peut pas être terminé s'il
- * détient un mutex. Pendant de safeLock.
+//! Déverrouille un mutex.
+/*!
+ * S'assure que le thread courant ne peut pas être terminé s'il
+ * détient un mutex. Pendant de safeLock.
*
- * \param mutex le mutex à déverrouiller
+ * \param mutex le mutex à déverrouiller
*
* \see safeLock
*/
thread->setTerminationEnabled(true);
}
-/*! Marque l'image entière comme non à jour.
- */
+//! Marque l'image entière comme non à jour.
inline
void DrawingWindow::dirty()
{
dirtyRect = image->rect();
}
-/*! Marque un point de l'image comme non à jour.
- *
- * \param x, y coordonnées du point
+//! Marque un point de l'image comme non à jour.
+/*!
+ * \param x, y coordonnées du point
*/
inline
void DrawingWindow::dirty(int x, int y)
dirty(QRect(x, y, 1, 1));
}
-/*! Marque une zone de l'image comme non à jour.
+//! Marque une zone de l'image comme non à jour.
+/*!
+ * La zone est définie par un rectangle dont les coordonnées de deux
+ * sommets oppposés sont données.
*
- * La zone est définie par un rectangle dont les coordonnées de deux
- * sommets oppposés sont données.
- *
- * \param x1, y1 coordonnées d'un sommet du rectangle
- * \param x2, y2 coordonnées du sommet opposé du rectangle
+ * \param x1, y1 coordonnées d'un sommet du rectangle
+ * \param x2, y2 coordonnées du sommet opposé du rectangle
*/
inline
void DrawingWindow::dirty(int x1, int y1, int x2, int y2)
dirty(r.normalized());
}
-/*! Marque une zone de l'image comme non à jour.
- *
- * \param rect rectangle délimitant la zone
+//! Marque une zone de l'image comme non à jour.
+/*!
+ * \param rect rectangle délimitant la zone
*/
void DrawingWindow::dirty(const QRect &rect)
{
}
}
-/*! Génère un update si besoin.
- *
- * Génère une demande de mise à jour de la fenêtre (appel à update)
+//! Génère un update si besoin.
+/*!
+ * Génère une demande de mise à jour de la fenêtre (appel à update)
* s'il y en a besoin.
*/
void DrawingWindow::mayUpdate()
update(rect);
}
-/*! Fonction bas-niveau pour sync.
- *
+//! Fonction bas-niveau pour sync.
+/*!
* Fonction de synchronisation dans le thread principal.
*
* \see sync, customEvent
syncMutex.unlock();
}
-/*! Fonction bas-niveau pour drawText.
- *
- * Le rendu de texte doit être fait dans le thread principal. D'où
+//! Fonction bas-niveau pour drawText.
+/*!
+ * Le rendu de texte doit être fait dans le thread principal. D'où
* les manipulations tordues et la synchronisation qui s'en suit.
*
* \param x, y, text, flags cf. drawText
r.setTop(y);
}
syncMutex.lock();
- painter->drawText(r, flags, text, &r);
+ painter->drawText(r, flags, QString::fromUtf8(text), &r);
dirty(r);
syncCondition.wakeAll();
syncMutex.unlock();
//--- DrawingThread ----------------------------------------------------
-/*! Constructeur.
- */
+//! Constructeur.
DrawingThread::DrawingThread(DrawingWindow &w, DrawingWindow::ThreadFunction f)
: drawingWindow(w)
, threadFunction(f)
{
}
-/*! Démarre le thread si ce n'a pas encore été fait.
- */
+//! Démarre le thread si ce n'a pas encore été fait.
void DrawingThread::start_once(Priority priority)
{
if (!started_once) {
}
}
-/*! La vraie fonction pour le thread.
- */
+//! La vraie fonction pour le thread.
void DrawingThread::run()
{
threadFunction(drawingWindow);