gridview.hpp 6.85 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
\file gridview.hpp
\date 28/04/2021
\author Yann Boucher
\version 1
\brief GridView

Cette classe représente le widget utilisé pour l'affichage et l'interaction avec la grille actuelle.
**/

#ifndef GRIDVIEW_HPP
#define GRIDVIEW_HPP

14
#include <map>
15
#include <set>
16

17
18
#include <QFrame>
#include <QGraphicsView>
19
#include <QLabel>
20
21
22
23
24

#include <QGraphicsRectItem>

#include "coord.hpp"
#include "structure.hpp"
25
#include "alphabet.hpp"
26
27

#include "grid.h"
28
#include "history.h"
29
30
31

namespace detail
{
Yann Boucher's avatar
Yann Boucher committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//! \class Graphics_view_zoom
//! Classe permettant l'implémentation d'un zoom au travers d'un event filter.
//! Détail d'implémentation.
//! based on https://stackoverflow.com/questions/19113532/qgraphicsview-zooming-in-and-out-under-mouse-position-using-mouse-wheel
class Graphics_view_zoom : public QObject {
    Q_OBJECT
public:
    Graphics_view_zoom(QGraphicsView* view);
    void gentle_zoom(double factor);
    void set_zoom_factor_base(double value);

private:
    QGraphicsView* _view;
    double _zoom_factor_base;
    QPointF target_scene_pos, target_viewport_pos;
    bool eventFilter(QObject* object, QEvent* event);

signals:
    void zoomed();
};
52
}
53

54
class GridView;
55
class GridGraphicsView;
56
class DragDropHandlerItem;
57

58
59
60
61
62
63
64
/**
 * \class GridView
 * \brief Widget affichant la grille en cours
 *
 * Cette classe, hérité de QFrame, représente l'état de la grille à l'instant actuel. Il affiche les différentes cellules avec la couleur choisie par l'alphabet,
 * permet l'édition, la suppression, le copier-couper-coller, et le glisser-déposer de structures depuis d'autres widget.
 */
65
66
67
class GridView : public QFrame
{
    Q_OBJECT
68
69

    friend class GridGraphicsView;
70
public:
71
    //! \brief Initialise le GridView comme n'importe quel autre QWidget avec son parent.
72
    GridView(QWidget *parent = nullptr);
73
public:
74
75
    //! \brief Associe l'alphabet alph à l'objet GridView afin d'afficher les bonnes couleurs et étiquettes.
    //! \param alph L'alphabet à associer.
76
    void set_alphabet(const Alphabet& alph);
77
78
    //! \brief Retourne l'alphabet actuel utilisé par le GridView.
    //! \returns L'alphabet actuellement utilisé
79
80
    const Alphabet& alphabet() const;

81
82
    //! \brief Paramètre l'état à assigner aux cellules lors de l'édition (le 'stylo' actuel)
    //! \param state L'état à assigner à chaque cellule éditée.
83
    void set_current_pen(unsigned state);
84
85
    //! \brief Retoure l'état actuel du stylo.
    //! \returns L'état actuel de l'édition.
86
    unsigned current_pen() const;
87

88
89
90
91
    //! \brief Active le mode "toggle", qui permet de changer l'état d'une cellule de manière cyclique en cliquant dessus, passant d'un état check à uncheck, et inversement si cliqué à nouveau.
    //! \param checked_state L'état lorsqu'une cellule est sélectionnée
    //! \param unchecked_state L'état d'une cellule non sélectionnée
    void enable_toggle_mode(unsigned checked_state, unsigned unchecked_state = 0);
92
93
94
95
96
    //! \brief Ajoute une règle au mode "toggle", qui permet de changer l'état d'une cellule de manière cyclique en cliquant dessus, passant d'un état check à uncheck, et inversement si cliqué à nouveau.
    //! \brief Cette fonction permet d'ajouter une nouvellle paire d'états cycliques, pour pouvoir par exemple permettre de passer entre 0-1 et 2-3, indépendamment.
    //! \param checked_state L'état d'une cellule sélectionnée
    //! \param unchecked_state L'état d'une cellule non sélectionnée
    void add_toggle_rule(unsigned checked_state, unsigned unchecked_state = 0);
97
98
99
100
101
102
    //! \brief Désactive le mode "toggle".
    void disable_toggle_mode();
    //! \brief Retourne un booléen indiquant si le mode actuel est le mode "toggle".
    bool in_toggle_mode() const
    { return m_in_toggle_mode; }

103
104
105
    //! \brief Insère une structure à une position donnée.
    //! \param origin La coordonnée où placer la structure.
    //! \param s La structure à placer.
106
107
    void paste_structure_at(Coord origin, const Structure& s);

108
109
    //! \brief Utilise une structure passée en argument comme structure à coller lors d'une opération de collage, par exemple avec Ctrl+V.
    //! \param s La structure désirée.
110
111
    void set_clipboard(const Structure& s);

112
113
    //! \brief Retourne la taille du côté en pixels d'une cellule au niveau de zoom actuel.
    //! \returns Taille en pixel du côté d'une cellule.
114
    unsigned cell_screen_size() const;
115

116
117
118
119
    //! \brief Retourne la taille de la grille, dans un QSize.
    //! \returns La taille de la Grid.
    QSize grid_size() const;

120
121
    //! \brief Charge la Grid grid dans le GridView afin de l'afficher et de pouvoir l'éditer.
    //! \param grid La Grid à copier vers l'affichage du GridView.
122
    void copy_grid(const Grid& grid);
123
    //! \brief Retourne une Grid représentant l'état actuel affiché par la GridView.
124
125
    //! \returns Une référence constante vers une Grid correspondante.
    const Grid &get_grid() const;
126

127
    //! \brief Réinitialise la sélection.
128
    void clear_selection();
129
130
    //! \brief Remplit les cellules sélectionnées avec un état choisi.
    //! \param state L'état à assigner.
131
    void fill_selection(unsigned state);
132
133
    //! \brief Retourne une structure représentant la sélection actuelle.
    //! \returns Une structure représentant la sélection actuelle.
134
135
    Structure selected_cells() const;

136
137
138
139
140
141
    //! \brief Sauvegarde l'état de la grille avant une opération de modification, pour pouvoir Ctrl-Z.
    void push_history();

    //! \brief Annule la dernière opération (effectue un Ctrl-Z).
    void undo();

142
signals:
143
    //! \brief Signal émis quand le zoom change.
144
145
146
    //! \param cell_size la nouvelle taille à l'écran en pixels d'une cellule
    void zoom_changed(unsigned cell_size);

147
private:
148
149
    void load_grid(const Grid& grid);

150
151
152
    void set_cell_state(Coord pos, unsigned state);
    void update_gridview();

153
    QGraphicsRectItem* create_selection_rect(const QRectF &rect = QRectF());
154
155
156
    void copy_selection();
    void paste_clipboard();
    void delete_selection();
157
    void select_all();
158

159
    void click_on(Coord coord);
160
    void update_current_mouse_pos(Coord coord);
161

162
163
164
165
166
    const QPixmap &grid_pixmap() const;

private slots:
    void handle_rubberband(QRect, QPointF, QPointF);

167
168
169
170
171
protected:
    void keyPressEvent(QKeyEvent *event);
    void keyReleaseEvent(QKeyEvent *event);

private:
172
    GridGraphicsView* m_view;
173
    QGraphicsScene* m_scene;
174
    detail::Graphics_view_zoom* m_zoom;
175
    History m_undo_history;
176
177
    QImage m_grid_image;
    QPixmap m_grid_pixmap;
178
    QLabel* m_mouse_pos_label;
179
    Grid m_grid;
180
    Coord m_last_mouse_pos;
181
    bool m_in_toggle_mode;
182
    std::vector<std::pair<unsigned, unsigned>> m_toggle_states;
183
184
185
186
    std::vector<QGraphicsRectItem*> m_selection_rects;
    bool m_handling_rubberband;
    DragDropHandlerItem* m_drag_drop_handler;

187
188
    unsigned m_width;
    unsigned m_height;
189
    unsigned m_pen;
190
    Structure m_copy_paste_buffer;
191
    Alphabet m_alph;
192
193
194
};

#endif // GRIDVIEW_HPP