Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
LO21_Pin_Noir_Boucher_Bouri_Detree
CellulutLO21
Commits
88a33280
Commit
88a33280
authored
May 01, 2021
by
Yann Boucher
Browse files
Added base implementation of the Grid Widget
parent
cf58a96e
Pipeline
#77338
passed with stages
in 16 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
include/coord.hpp
View file @
88a33280
...
...
@@ -43,4 +43,23 @@ inline bool operator<(const Coord& lhs, const Coord& rhs)
return
lhs
.
x
<
rhs
.
x
;
}
//! \brief Addition de coordonnées
inline
Coord
operator
+
(
const
Coord
&
lhs
,
const
Coord
&
rhs
)
{
return
{
lhs
.
x
+
rhs
.
x
,
lhs
.
y
+
rhs
.
y
};
}
//! \brief Soustraction de coordonnées
inline
Coord
operator
-
(
const
Coord
&
lhs
,
const
Coord
&
rhs
)
{
return
{
lhs
.
x
-
rhs
.
x
,
lhs
.
y
-
rhs
.
y
};
}
//! \brief Retourne une coordonnée ajustée par rapport à un réseau périodique de taille (cols, rows)
inline
Coord
wrap_coords
(
const
Coord
&
coord
,
unsigned
cols
,
unsigned
rows
)
{
return
Coord
{
(
int
)((
coord
.
x
%
cols
+
cols
)
%
cols
),
(
int
)((
coord
.
y
%
rows
+
rows
)
%
rows
)
};
}
#endif // COORD_HPP
include/grid.h
View file @
88a33280
...
...
@@ -19,6 +19,8 @@ Cette classe représente un réseau de cellules.
using
namespace
std
;
// TODO : documenter
class
Grid
{
int
nb_rows
;
int
nb_col
;
...
...
include/gridview.hpp
View file @
88a33280
...
...
@@ -11,6 +11,10 @@ Cette classe représente le widget utilisé pour l'affichage et l'interaction av
#ifndef GRIDVIEW_HPP
#define GRIDVIEW_HPP
// TODO : documenter
#include
<map>
#include
<QFrame>
#include
<QGraphicsView>
...
...
@@ -21,6 +25,7 @@ Cette classe représente le widget utilisé pour l'affichage et l'interaction av
#include
"grid.h"
class
GridItem
;
class
GridView
:
public
QFrame
{
Q_OBJECT
...
...
@@ -34,6 +39,14 @@ public:
void
clear_selection
();
Structure
selected_cells
()
const
;
private:
GridItem
*
item_at
(
Coord
pos
);
void
copy_selection
();
void
paste_clipboard
();
void
delete_selection
();
Coord
top_left_of_selection
()
const
;
protected:
void
keyPressEvent
(
QKeyEvent
*
event
);
void
keyReleaseEvent
(
QKeyEvent
*
event
);
...
...
@@ -41,6 +54,7 @@ protected:
private:
QGraphicsView
*
m_view
;
QGraphicsScene
*
m_scene
;
Structure
m_copy_paste_buffer
;
};
...
...
include/structure.hpp
View file @
88a33280
...
...
@@ -59,6 +59,11 @@ public:
m_cells
[
it
->
first
]
=
it
->
second
;
}
}
//! \brief Fonction vidant la structure, la laissant vide.
void
clear
()
{
m_cells
.
clear
();
}
//! \brief retourne le nombre de cellules présentes dans la structure
size_t
size
()
const
...
...
src/gridview.cpp
View file @
88a33280
...
...
@@ -21,13 +21,15 @@ Cette classe représente le widget utilisé pour l'affichage et l'interaction av
#include
<QDebug>
#include
<vector>
#include
<qmath.h>
class
GridItem
:
public
QGraphicsRectItem
{
public:
GridItem
(
QColor
color
,
const
QString
&
state_name
,
QGraphicsItem
*
parent
=
nullptr
)
:
QGraphicsRectItem
(
0
,
0
,
20
,
20
,
parent
),
m_state_name
(
state_name
)
:
QGraphicsRectItem
(
0
,
0
,
GridItem
::
width
(),
GridItem
::
height
()
,
parent
),
m_state_name
(
state_name
)
{
setAcceptHoverEvents
(
true
);
setPen
(
QPen
(
QBrush
(
color
),
0
));
...
...
@@ -36,6 +38,11 @@ public:
setFlag
(
QGraphicsItem
::
ItemIsSelectable
);
}
static
int
width
()
{
return
20
;
}
static
int
height
()
{
return
20
;
}
protected:
void
paint
(
QPainter
*
painter
,
const
QStyleOptionGraphicsItem
*
option
,
QWidget
*
widget
)
{
...
...
@@ -76,7 +83,7 @@ GridView::GridView(QWidget *parent)
//m_scene->setBackgroundBrush(Qt::black);
m_view
=
new
QGraphicsView
(
this
);
m_view
->
setRenderHint
(
QPainter
::
Antialiasing
,
tru
e
);
m_view
->
setRenderHint
(
QPainter
::
Antialiasing
,
fals
e
);
m_view
->
setDragMode
(
QGraphicsView
::
RubberBandDrag
);
m_view
->
setOptimizationFlags
(
QGraphicsView
::
DontSavePainterState
);
m_view
->
setViewportUpdateMode
(
QGraphicsView
::
SmartViewportUpdate
);
...
...
@@ -101,8 +108,10 @@ GridView::GridView(QWidget *parent)
{
QColor
color
(
Qt
::
black
);
QGraphicsRectItem
*
item
=
new
GridItem
((
i
^
j
)
%
2
?
Qt
::
white
:
Qt
::
blue
,
(
i
^
j
)
%
2
?
"Alive"
:
"Dead"
);
item
->
setPos
(
QPointF
(
i
*
20
,
j
*
20
));
GridItem
*
item
=
new
GridItem
((
i
^
j
)
%
2
?
Qt
::
blue
:
Qt
::
white
,
(
i
^
j
)
%
2
?
"Alive"
:
"Dead"
);
item
->
setPos
(
QPointF
(
i
*
GridItem
::
width
(),
j
*
GridItem
::
height
()));
item
->
cell_pos
=
Coord
{(
int
)
i
,
(
int
)
j
};
item
->
cell_state
=
(
i
^
j
)
%
2
;
m_scene
->
addItem
(
item
);
}
}
...
...
@@ -119,8 +128,10 @@ void GridView::copy_grid(const Grid &grid)
QColor
color
(
Qt
::
black
);
unsigned
state
=
grid
.
get_state
(
j
,
i
);
// TODO : récupérer state color
QGraphicsRectItem
*
item
=
new
GridItem
((
i
^
j
)
%
2
?
Qt
::
white
:
Qt
::
blue
,
(
i
^
j
)
%
2
?
"Alive"
:
"Dead"
);
item
->
setPos
(
QPointF
(
i
*
20
,
j
*
20
));
GridItem
*
item
=
new
GridItem
((
i
^
j
)
%
2
?
Qt
::
blue
:
Qt
::
white
,
(
i
^
j
)
%
2
?
"Alive"
:
"Dead"
);
item
->
setPos
(
QPointF
(
i
*
GridItem
::
width
(),
j
*
GridItem
::
height
()));
item
->
cell_pos
=
Coord
{(
int
)
i
,
(
int
)
j
};
item
->
cell_state
=
state
;
m_scene
->
addItem
(
item
);
}
}
...
...
@@ -139,21 +150,119 @@ void GridView::clear_selection()
Structure
GridView
::
selected_cells
()
const
{
if
(
m_scene
->
selectedItems
().
empty
())
return
Structure
{};
std
::
vector
<
std
::
pair
<
Coord
,
unsigned
>>
cells
;
// on calcule la position du coin supérieur gauche de la sélection, afin de la considérer comme l'origine de de la structure
Coord
origin
=
top_left_of_selection
();
for
(
const
auto
&
item
:
m_scene
->
selectedItems
())
{
GridItem
*
cell
=
static_cast
<
GridItem
*>
(
item
);
cells
.
push_back
(
std
::
make_pair
(
cell
->
cell_pos
,
cell
->
cell_state
));
cells
.
push_back
(
std
::
make_pair
(
cell
->
cell_pos
-
origin
,
cell
->
cell_state
));
}
return
Structure
(
cells
.
begin
(),
cells
.
end
());
}
GridItem
*
GridView
::
item_at
(
Coord
pos
)
{
QGraphicsItem
*
gitem_ptr
=
m_scene
->
itemAt
(
QPointF
(
pos
.
x
*
GridItem
::
width
(),
pos
.
y
*
GridItem
::
height
()),
QTransform
());
return
dynamic_cast
<
GridItem
*>
(
gitem_ptr
);
}
void
GridView
::
copy_selection
()
{
m_copy_paste_buffer
=
selected_cells
();
}
void
GridView
::
paste_clipboard
()
{
// la destination est la cellule sélectionnée actuelle, on ne fait rien si on est pas dans ce cas
if
(
m_scene
->
selectedItems
().
size
()
<
1
)
return
;
Coord
origin
=
top_left_of_selection
();
for
(
const
auto
&
cell
:
m_copy_paste_buffer
)
{
Coord
corrected
=
wrap_coords
(
cell
.
first
+
origin
,
100
,
100
);
GridItem
*
item
=
item_at
(
corrected
);
assert
(
item
!=
nullptr
);
item
->
cell_state
=
cell
.
second
;
item
->
setBrush
(
QBrush
(
cell
.
second
?
Qt
::
blue
:
Qt
::
white
));
item
->
update
();
}
}
void
GridView
::
delete_selection
()
{
for
(
auto
&
abstract_item
:
m_scene
->
selectedItems
())
{
GridItem
*
item
=
static_cast
<
GridItem
*>
(
abstract_item
);
item
->
setBrush
(
QBrush
(
Qt
::
white
));
item
->
cell_state
=
0
;
item
->
update
();
}
clear_selection
();
}
Coord
GridView
::
top_left_of_selection
()
const
{
// on calcule la position du coin supérieur gauche de la sélection
Coord
selection_top_left
=
Coord
{
std
::
numeric_limits
<
int
>::
max
(),
std
::
numeric_limits
<
int
>::
max
()};
for
(
const
auto
&
item
:
m_scene
->
selectedItems
())
{
GridItem
*
cell
=
static_cast
<
GridItem
*>
(
item
);
if
(
cell
->
cell_pos
.
x
<
selection_top_left
.
x
)
selection_top_left
.
x
=
cell
->
cell_pos
.
x
;
if
(
cell
->
cell_pos
.
y
<
selection_top_left
.
y
)
selection_top_left
.
y
=
cell
->
cell_pos
.
y
;
}
return
selection_top_left
;
}
void
GridView
::
keyPressEvent
(
QKeyEvent
*
event
)
{
if
(
event
->
modifiers
()
&
Qt
::
ShiftModifier
)
{
// prevent items from stealing the mouse event
for
(
auto
&
item
:
m_scene
->
items
())
item
->
setAcceptedMouseButtons
(
Qt
::
NoButton
);
m_view
->
setDragMode
(
QGraphicsView
::
ScrollHandDrag
);
}
// copier-couper-coller
if
(
event
->
modifiers
()
&
Qt
::
ControlModifier
)
{
if
(
event
->
key
()
==
Qt
::
Key_C
)
{
copy_selection
();
}
else
if
(
event
->
key
()
==
Qt
::
Key_X
)
{
copy_selection
();
delete_selection
();
}
else
if
(
event
->
key
()
==
Qt
::
Key_V
)
{
paste_clipboard
();
}
}
// suppression de sélection
if
(
event
->
key
()
==
Qt
::
Key_Backspace
||
event
->
key
()
==
Qt
::
Key_Delete
)
{
delete_selection
();
}
return
QFrame
::
keyPressEvent
(
event
);
}
void
GridView
::
keyReleaseEvent
(
QKeyEvent
*
event
)
...
...
@@ -162,8 +271,12 @@ void GridView::keyReleaseEvent(QKeyEvent *event)
if
(
QGuiApplication
::
keyboardModifiers
()
&
Qt
::
ShiftModifier
)
{
m_view
->
setDragMode
(
QGraphicsView
::
RubberBandDrag
);
// prevent item mouse event handling
for
(
auto
&
item
:
m_scene
->
items
())
item
->
setAcceptedMouseButtons
(
Qt
::
AllButtons
);
}
return
QFrame
::
keyReleaseEvent
(
event
);
}
detail
::
Graphics_view_zoom
::
Graphics_view_zoom
(
QGraphicsView
*
view
)
...
...
tests/coord_tests.cpp
View file @
88a33280
...
...
@@ -18,5 +18,9 @@ void CellulutTests::test_coord()
QVERIFY
(
b
==
b
);
QVERIFY
(
a
!=
b
);
QVERIFY
(
!
(
a
==
b
));
QCOMPARE
(
wrap_coords
(
Coord
{
3
,
4
},
2
,
2
),
(
Coord
{
1
,
0
}));
QCOMPARE
((
Coord
{
1
,
2
}
+
Coord
{
3
,
4
}),
(
Coord
{
4
,
6
}));
QCOMPARE
((
Coord
{
1
,
2
}
-
Coord
{
3
,
4
}),
(
Coord
{
-
2
,
-
2
}));
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment