Commit bef2a147 authored by Yann Boucher's avatar Yann Boucher
Browse files

A few more optimisations for GridView

parent e9d4fc04
Pipeline #78785 passed with stages
in 17 seconds
...@@ -95,6 +95,10 @@ public: ...@@ -95,6 +95,10 @@ public:
//! \returns Taille en pixel du côté d'une cellule. //! \returns Taille en pixel du côté d'une cellule.
unsigned cell_pixel_size() const; unsigned cell_pixel_size() const;
//! \brief Retourne la taille de la grille, dans un QSize.
//! \returns La taille de la Grid.
QSize grid_size() const;
//! \brief Charge la Grid grid dans le GridView afin de l'afficher et de pouvoir l'éditer. //! \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. //! \param grid La Grid à copier vers l'affichage du GridView.
void copy_grid(const Grid& grid); void copy_grid(const Grid& grid);
......
...@@ -19,6 +19,7 @@ Cette classe représente le widget utilisé pour l'affichage et l'interaction av ...@@ -19,6 +19,7 @@ Cette classe représente le widget utilisé pour l'affichage et l'interaction av
#include <QToolTip> #include <QToolTip>
#include <QLabel> #include <QLabel>
#include <QMimeData> #include <QMimeData>
#include <QStyleOptionGraphicsItem>
#include <QDebug> #include <QDebug>
...@@ -94,12 +95,11 @@ public: ...@@ -94,12 +95,11 @@ public:
setToolTip(m_state_name); setToolTip(m_state_name);
setFlag(QGraphicsItem::ItemIsSelectable); setFlag(QGraphicsItem::ItemIsSelectable);
setAcceptDrops(true); setAcceptDrops(true);
//setCacheMode(QGraphicsItem::DeviceCoordinateCache);
set_state(state); set_state(state);
set_grid_pos(pos); set_grid_pos(pos);
setPen(QPen(brush(), 0)); setPen(QPen(brush(), 0));
m_view = nullptr;
} }
static int width() static int width()
...@@ -132,20 +132,9 @@ public: ...@@ -132,20 +132,9 @@ public:
protected: protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{ {
if (!m_view) QRectF rect = QRectF(0, 0, GridItem::width(), GridItem::height());
{
assert(scene()->views().size() != 0);
m_view = scene()->views().first();
}
QSizeF screen_size = m_view->transform().mapRect(sceneBoundingRect()).size();
QRectF rect = QRectF(0, 0, width(), height()); painter->setPen(Qt::NoPen);
if (screen_size.width() < 7.5)
painter->setPen(Qt::NoPen); // if the cell is too small, don't draw its outline
else
painter->setPen(QPen(Qt::black, 0)); // cosmetic 1-pixel pen
if (isSelected()) if (isSelected())
{ {
...@@ -193,7 +182,6 @@ private: ...@@ -193,7 +182,6 @@ private:
Coord m_cell_pos; Coord m_cell_pos;
unsigned m_cell_state; unsigned m_cell_state;
QString m_state_name; QString m_state_name;
QGraphicsView* m_view;
GridView& m_grid_view; GridView& m_grid_view;
}; };
...@@ -215,6 +203,7 @@ public: ...@@ -215,6 +203,7 @@ public:
protected: protected:
void mousePressEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event);
void drawForeground(QPainter * painter, const QRectF & rect);
private: private:
void draw_bresenham(QPointF from, QPointF to); void draw_bresenham(QPointF from, QPointF to);
...@@ -227,8 +216,9 @@ private: ...@@ -227,8 +216,9 @@ private:
void GridGraphicsView::mousePressEvent(QMouseEvent *event) void GridGraphicsView::mousePressEvent(QMouseEvent *event)
{ {
QGraphicsItem* gitem_ptr = itemAt(event->pos()); QPointF item_pos = mapToScene(event->pos());
GridItem* item = dynamic_cast<GridItem*>(gitem_ptr); Coord coord = Coord{(int)item_pos.x()/GridItem::width(), (int)item_pos.y()/GridItem::height()};
GridItem* item = m_gridview.item_at(coord);
m_last_mouse_pos = event->pos(); m_last_mouse_pos = event->pos();
...@@ -251,8 +241,9 @@ void GridGraphicsView::mousePressEvent(QMouseEvent *event) ...@@ -251,8 +241,9 @@ void GridGraphicsView::mousePressEvent(QMouseEvent *event)
void GridGraphicsView::mouseMoveEvent(QMouseEvent *event) void GridGraphicsView::mouseMoveEvent(QMouseEvent *event)
{ {
QGraphicsItem* gitem_ptr = itemAt(event->pos()); QPointF item_pos = mapToScene(event->pos());
GridItem* item = dynamic_cast<GridItem*>(gitem_ptr); Coord coord = Coord{(int)item_pos.x()/GridItem::width(), (int)item_pos.y()/GridItem::height()};
GridItem* item = m_gridview.item_at(coord);
if (QGuiApplication::keyboardModifiers() == Qt::NoModifier && event->buttons() == Qt::LeftButton) if (QGuiApplication::keyboardModifiers() == Qt::NoModifier && event->buttons() == Qt::LeftButton)
{ {
...@@ -269,6 +260,34 @@ void GridGraphicsView::mouseMoveEvent(QMouseEvent *event) ...@@ -269,6 +260,34 @@ void GridGraphicsView::mouseMoveEvent(QMouseEvent *event)
m_last_mouse_pos = event->pos(); m_last_mouse_pos = event->pos();
} }
void GridGraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
{
qreal lod = QStyleOptionGraphicsItem::levelOfDetailFromTransform(painter->worldTransform());
if (lod < 0.4)
return; // trop zoomé, on ne dessine rien
painter->setPen(QPen(Qt::black, 0)); // cosmetic 1-pixel pen
QVector<QLine> lines;
// horizontal lines
for (int i = -1; i < m_gridview.grid_size().height(); ++i)
{
const unsigned y_offset = (i+1)*GridItem::height();
lines.append(QLine(QPoint(0, y_offset), QPoint(GridItem::width()*m_gridview.grid_size().width(), y_offset)));
}
// vertical lines
for (int j = -1; j < m_gridview.grid_size().width(); ++j)
{
const unsigned x_offset = (j+1)*GridItem::width();
lines.append(QLine(QPoint(x_offset, 0), QPoint(x_offset, GridItem::height()*m_gridview.grid_size().height())));
}
painter->drawLines(lines);
painter->setPen(Qt::NoPen);
}
// Algorithme de Bresenham pour tracer une ligne entre les deux points et dessiner sur ces items // Algorithme de Bresenham pour tracer une ligne entre les deux points et dessiner sur ces items
void GridGraphicsView::draw_bresenham(QPointF from, QPointF to) void GridGraphicsView::draw_bresenham(QPointF from, QPointF to)
{ {
...@@ -298,7 +317,7 @@ void GridGraphicsView::draw_bresenham(QPointF from, QPointF to) ...@@ -298,7 +317,7 @@ void GridGraphicsView::draw_bresenham(QPointF from, QPointF to)
GridView::GridView(QWidget *parent) GridView::GridView(QWidget *parent)
: QFrame(parent), m_undo_history(10), m_width(10), m_height(10) : QFrame(parent), m_undo_history(10), m_width(10), m_height(10)
{ {
setMouseTracking(true); //setMouseTracking(true);
setFrameStyle(Sunken | StyledPanel); setFrameStyle(Sunken | StyledPanel);
...@@ -314,6 +333,13 @@ GridView::GridView(QWidget *parent) ...@@ -314,6 +333,13 @@ GridView::GridView(QWidget *parent)
m_view->viewport()->setCursor(Qt::ArrowCursor); m_view->viewport()->setCursor(Qt::ArrowCursor);
m_view->setBackgroundBrush(QBrush(Qt::gray)); m_view->setBackgroundBrush(QBrush(Qt::gray));
m_view->setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect); // provides better performance m_view->setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect); // provides better performance
/*
QOpenGLWidget *gl = new QOpenGLWidget();
QSurfaceFormat format;
format.setSamples(4);
gl->setFormat(format);
m_view->setViewport(gl);
*/
m_zoom = new detail::Graphics_view_zoom(m_view); m_zoom = new detail::Graphics_view_zoom(m_view);
...@@ -372,13 +398,12 @@ void GridView::set_clipboard(const Structure &s) ...@@ -372,13 +398,12 @@ void GridView::set_clipboard(const Structure &s)
unsigned GridView::cell_pixel_size() const unsigned GridView::cell_pixel_size() const
{ {
if (m_view->items().empty()) return m_view->transform().mapRect(QRectF(0,0,GridItem::width(), GridItem::height())).size().toSize().width();
return 10; // a default size if there are no cells in the grid yet }
const GridItem* item = item_at({0, 0});
assert(item);
return m_view->transform().mapRect(item->sceneBoundingRect()).size().toSize().width(); QSize GridView::grid_size() const
{
return QSize(m_width, m_height);
} }
void GridView::copy_grid(const Grid &grid) void GridView::copy_grid(const Grid &grid)
...@@ -443,12 +468,16 @@ void GridView::undo() ...@@ -443,12 +468,16 @@ void GridView::undo()
GridItem *GridView::item_at(Coord pos) GridItem *GridView::item_at(Coord pos)
{ {
if (pos.x < 0 || pos.y < 0 || pos.x >= (int)m_width || pos.y >= (int)m_height)
return nullptr;
return m_item_cache[pos.y*m_width + pos.x]; return m_item_cache[pos.y*m_width + pos.x];
//QGraphicsItem* gitem_ptr = m_scene->itemAt(QPointF(pos.x*GridItem::width(), pos.y*GridItem::height()), QTransform()); //QGraphicsItem* gitem_ptr = m_scene->itemAt(QPointF(pos.x*GridItem::width(), pos.y*GridItem::height()), QTransform());
//return dynamic_cast<GridItem*>(gitem_ptr); //return dynamic_cast<GridItem*>(gitem_ptr);
} }
const GridItem *GridView::item_at(Coord pos) const const GridItem *GridView::item_at(Coord pos) const
{ {
if (pos.x < 0 || pos.y < 0 || pos.x >= (int)m_width || pos.y >= (int)m_height)
return nullptr;
return m_item_cache[pos.y*m_width + pos.x]; return m_item_cache[pos.y*m_width + pos.x];
//QGraphicsItem* gitem_ptr = m_scene->itemAt(QPointF(pos.x*GridItem::width(), pos.y*GridItem::height()), QTransform()); //QGraphicsItem* gitem_ptr = m_scene->itemAt(QPointF(pos.x*GridItem::width(), pos.y*GridItem::height()), QTransform());
//return dynamic_cast<GridItem*>(gitem_ptr); //return dynamic_cast<GridItem*>(gitem_ptr);
...@@ -456,27 +485,46 @@ const GridItem *GridView::item_at(Coord pos) const ...@@ -456,27 +485,46 @@ const GridItem *GridView::item_at(Coord pos) const
void GridView::load_grid(const Grid &grid) void GridView::load_grid(const Grid &grid)
{ {
m_scene->clear();
m_height = grid.get_rows(); m_height = grid.get_rows();
m_width = grid.get_col(); m_width = grid.get_col();
m_item_cache.clear(); if (m_height*m_width != m_item_cache.size())
m_item_cache.resize(m_width*m_height);
// Populate scene;
for (unsigned i = 0; i < m_width; ++i)
{ {
for (unsigned j = 0; j < m_height; ++j) m_scene->clear();
m_item_cache.resize(m_width*m_height);
// Populate scene;
for (unsigned i = 0; i < m_width; ++i)
{ {
Coord pos = {static_cast<int>(i), static_cast<int>(j)}; for (unsigned j = 0; j < m_height; ++j)
unsigned state = grid.get_state(pos); {
Coord pos = {static_cast<int>(i), static_cast<int>(j)};
unsigned state = grid.get_state(pos);
GridItem *item = new GridItem(*this, state);
item->set_grid_pos(pos);
m_item_cache[pos.y*m_width + pos.x] = item;
m_scene->addItem(item);
}
}
GridItem *item = new GridItem(*this, state); // On met à jour la taille de la scène
item->set_grid_pos(pos); QRectF rect = m_scene->itemsBoundingRect();
m_item_cache[pos.y*m_width + pos.x] = item; m_scene->setSceneRect(rect);
m_scene->addItem(item); }
// Pas la peine de recharger la grille si la taille est la même
else
{
for (unsigned i = 0; i < m_width; ++i)
{
for (unsigned j = 0; j < m_height; ++j)
{
Coord pos = {static_cast<int>(i), static_cast<int>(j)};
unsigned state = grid.get_state(pos);
GridItem *item = item_at(pos);
item->set_state(state);
}
} }
} }
m_width = grid.get_col();
m_height = grid.get_rows();
} }
void GridView::copy_selection() void GridView::copy_selection()
...@@ -551,7 +599,7 @@ void GridView::keyPressEvent(QKeyEvent *event) ...@@ -551,7 +599,7 @@ void GridView::keyPressEvent(QKeyEvent *event)
if (event->modifiers() & Qt::ShiftModifier) if (event->modifiers() & Qt::ShiftModifier)
{ {
// prevent items from stealing the mouse event // prevent items from stealing the mouse event
for (auto& item : m_scene->items()) for (auto& item : m_item_cache)
item->setAcceptedMouseButtons(Qt::NoButton); item->setAcceptedMouseButtons(Qt::NoButton);
m_view->setDragMode(QGraphicsView::ScrollHandDrag); m_view->setDragMode(QGraphicsView::ScrollHandDrag);
} }
...@@ -578,7 +626,7 @@ void GridView::keyPressEvent(QKeyEvent *event) ...@@ -578,7 +626,7 @@ void GridView::keyPressEvent(QKeyEvent *event)
} }
else if (event->key() == Qt::Key_A) else if (event->key() == Qt::Key_A)
{ {
for (auto& item : m_scene->items()) for (auto& item : m_item_cache)
item->setSelected(true); item->setSelected(true);
} }
else if (event->key() == Qt::Key_Plus) else if (event->key() == Qt::Key_Plus)
...@@ -608,7 +656,7 @@ void GridView::keyReleaseEvent(QKeyEvent *event) ...@@ -608,7 +656,7 @@ void GridView::keyReleaseEvent(QKeyEvent *event)
{ {
m_view->setDragMode(QGraphicsView::RubberBandDrag); m_view->setDragMode(QGraphicsView::RubberBandDrag);
// prevent item mouse event handling // prevent item mouse event handling
for (auto& item : m_scene->items()) for (auto& item : m_item_cache)
item->setAcceptedMouseButtons(Qt::AllButtons); item->setAcceptedMouseButtons(Qt::AllButtons);
} }
......
...@@ -201,7 +201,7 @@ void StructureLibraryView::create_drag(QTreeWidgetItem *item, int column) ...@@ -201,7 +201,7 @@ void StructureLibraryView::create_drag(QTreeWidgetItem *item, int column)
// set target size so that a single cell has the same size as the grid's cells // set target size so that a single cell has the same size as the grid's cells
target_size = QSize(s.width(), s.height()) * m_cell_pixel_size; target_size = QSize(s.width(), s.height()) * m_cell_pixel_size;
// Have a maximum size to avoid drawing huge megastructures all over the screen // Have a maximum size to avoid drawing huge megastructures all over the screen
const int max_size = 600; const int max_size = 1200;
if (target_size.width() >= max_size) if (target_size.width() >= max_size)
target_size.setWidth(max_size); target_size.setWidth(max_size);
if (target_size.height() >= max_size) if (target_size.height() >= max_size)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment