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:
//! \returns Taille en pixel du côté d'une cellule.
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.
//! \param grid La Grid à copier vers l'affichage du GridView.
void copy_grid(const Grid& grid);
......
......@@ -19,6 +19,7 @@ Cette classe représente le widget utilisé pour l'affichage et l'interaction av
#include <QToolTip>
#include <QLabel>
#include <QMimeData>
#include <QStyleOptionGraphicsItem>
#include <QDebug>
......@@ -94,12 +95,11 @@ public:
setToolTip(m_state_name);
setFlag(QGraphicsItem::ItemIsSelectable);
setAcceptDrops(true);
//setCacheMode(QGraphicsItem::DeviceCoordinateCache);
set_state(state);
set_grid_pos(pos);
setPen(QPen(brush(), 0));
m_view = nullptr;
}
static int width()
......@@ -132,20 +132,9 @@ public:
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
{
if (!m_view)
{
assert(scene()->views().size() != 0);
m_view = scene()->views().first();
}
QRectF rect = QRectF(0, 0, GridItem::width(), GridItem::height());
QSizeF screen_size = m_view->transform().mapRect(sceneBoundingRect()).size();
QRectF rect = QRectF(0, 0, width(), height());
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
painter->setPen(Qt::NoPen);
if (isSelected())
{
......@@ -193,7 +182,6 @@ private:
Coord m_cell_pos;
unsigned m_cell_state;
QString m_state_name;
QGraphicsView* m_view;
GridView& m_grid_view;
};
......@@ -215,6 +203,7 @@ public:
protected:
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void drawForeground(QPainter * painter, const QRectF & rect);
private:
void draw_bresenham(QPointF from, QPointF to);
......@@ -227,8 +216,9 @@ private:
void GridGraphicsView::mousePressEvent(QMouseEvent *event)
{
QGraphicsItem* gitem_ptr = itemAt(event->pos());
GridItem* item = dynamic_cast<GridItem*>(gitem_ptr);
QPointF item_pos = mapToScene(event->pos());
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();
......@@ -251,8 +241,9 @@ void GridGraphicsView::mousePressEvent(QMouseEvent *event)
void GridGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
QGraphicsItem* gitem_ptr = itemAt(event->pos());
GridItem* item = dynamic_cast<GridItem*>(gitem_ptr);
QPointF item_pos = mapToScene(event->pos());
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)
{
......@@ -269,6 +260,34 @@ void GridGraphicsView::mouseMoveEvent(QMouseEvent *event)
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
void GridGraphicsView::draw_bresenham(QPointF from, QPointF to)
{
......@@ -298,7 +317,7 @@ void GridGraphicsView::draw_bresenham(QPointF from, QPointF to)
GridView::GridView(QWidget *parent)
: QFrame(parent), m_undo_history(10), m_width(10), m_height(10)
{
setMouseTracking(true);
//setMouseTracking(true);
setFrameStyle(Sunken | StyledPanel);
......@@ -314,6 +333,13 @@ GridView::GridView(QWidget *parent)
m_view->viewport()->setCursor(Qt::ArrowCursor);
m_view->setBackgroundBrush(QBrush(Qt::gray));
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);
......@@ -372,13 +398,12 @@ void GridView::set_clipboard(const Structure &s)
unsigned GridView::cell_pixel_size() const
{
if (m_view->items().empty())
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(QRectF(0,0,GridItem::width(), GridItem::height())).size().toSize().width();
}
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)
......@@ -443,12 +468,16 @@ void GridView::undo()
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];
//QGraphicsItem* gitem_ptr = m_scene->itemAt(QPointF(pos.x*GridItem::width(), pos.y*GridItem::height()), QTransform());
//return dynamic_cast<GridItem*>(gitem_ptr);
}
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];
//QGraphicsItem* gitem_ptr = m_scene->itemAt(QPointF(pos.x*GridItem::width(), pos.y*GridItem::height()), QTransform());
//return dynamic_cast<GridItem*>(gitem_ptr);
......@@ -456,10 +485,11 @@ const GridItem *GridView::item_at(Coord pos) const
void GridView::load_grid(const Grid &grid)
{
m_scene->clear();
m_height = grid.get_rows();
m_width = grid.get_col();
m_item_cache.clear();
if (m_height*m_width != m_item_cache.size())
{
m_scene->clear();
m_item_cache.resize(m_width*m_height);
// Populate scene;
for (unsigned i = 0; i < m_width; ++i)
......@@ -475,8 +505,26 @@ void GridView::load_grid(const Grid &grid)
m_scene->addItem(item);
}
}
m_width = grid.get_col();
m_height = grid.get_rows();
// On met à jour la taille de la scène
QRectF rect = m_scene->itemsBoundingRect();
m_scene->setSceneRect(rect);
}
// 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);
}
}
}
}
void GridView::copy_selection()
......@@ -551,7 +599,7 @@ void GridView::keyPressEvent(QKeyEvent *event)
if (event->modifiers() & Qt::ShiftModifier)
{
// prevent items from stealing the mouse event
for (auto& item : m_scene->items())
for (auto& item : m_item_cache)
item->setAcceptedMouseButtons(Qt::NoButton);
m_view->setDragMode(QGraphicsView::ScrollHandDrag);
}
......@@ -578,7 +626,7 @@ void GridView::keyPressEvent(QKeyEvent *event)
}
else if (event->key() == Qt::Key_A)
{
for (auto& item : m_scene->items())
for (auto& item : m_item_cache)
item->setSelected(true);
}
else if (event->key() == Qt::Key_Plus)
......@@ -608,7 +656,7 @@ void GridView::keyReleaseEvent(QKeyEvent *event)
{
m_view->setDragMode(QGraphicsView::RubberBandDrag);
// prevent item mouse event handling
for (auto& item : m_scene->items())
for (auto& item : m_item_cache)
item->setAcceptedMouseButtons(Qt::AllButtons);
}
......
......@@ -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
target_size = QSize(s.width(), s.height()) * m_cell_pixel_size;
// 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)
target_size.setWidth(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