From 6255f283b54ecc00bd3979c6db649ef2245c236e Mon Sep 17 00:00:00 2001
From: yboucher <yann.boucher@etu.utc.fr>
Date: Tue, 1 Jun 2021 19:12:44 +0200
Subject: [PATCH] Fixed an issue with cell selection

---
 include/gridview.hpp |  5 ++-
 src/gridview.cpp     | 84 +++++++++++++++++++++-----------------------
 2 files changed, 43 insertions(+), 46 deletions(-)

diff --git a/include/gridview.hpp b/include/gridview.hpp
index 35d323f..857441c 100644
--- a/include/gridview.hpp
+++ b/include/gridview.hpp
@@ -134,11 +134,11 @@ private:
     void set_cell_state(Coord pos, unsigned state);
     void update_gridview();
 
+    QGraphicsRectItem* create_selection_rect(const QRectF &rect = QRectF());
     void copy_selection();
     void paste_clipboard();
     void delete_selection();
-
-    Coord top_left_of_selection() const;
+    void select_all();
 
     const QPixmap &grid_pixmap() const;
 
@@ -157,7 +157,6 @@ private:
     QImage m_grid_image;
     QPixmap m_grid_pixmap;
     Grid m_grid;
-    std::set<Coord> m_selected_cells;
     std::vector<QGraphicsRectItem*> m_selection_rects;
     bool m_handling_rubberband;
     DragDropHandlerItem* m_drag_drop_handler;
diff --git a/src/gridview.cpp b/src/gridview.cpp
index ac0dfdc..efa5a00 100644
--- a/src/gridview.cpp
+++ b/src/gridview.cpp
@@ -293,6 +293,7 @@ GridView::GridView(QWidget *parent)
     m_view->viewport()->setCursor(Qt::ArrowCursor);
     m_view->setBackgroundBrush(QBrush(Qt::gray));
     m_view->setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect); // provides better performance
+    m_view->scale(20, 20); // Begin with 20x20 pixels cells
 
     m_zoom = new detail::Graphics_view_zoom(m_view);
 
@@ -382,20 +383,21 @@ void GridView::clear_selection()
         m_scene->removeItem(rect);
     }
     m_selection_rects.clear();
-    m_selected_cells.clear();
     m_handling_rubberband = false;
 }
 
 Structure GridView::selected_cells() const
 {
-    if (m_scene->selectedItems().empty())
-        return Structure{};
-
     std::vector<std::pair<Coord, unsigned>> cells;
 
-    for (auto coord : m_selected_cells)
+    for (const auto& item : m_selection_rects)
     {
-        cells.push_back(std::make_pair(coord, m_grid.get_state(coord)));
+        const auto& rect = item->rect().toRect();
+        for (int i = rect.top(); i <= rect.bottom(); ++i)
+            for (int j = rect.left(); j <= rect.right(); ++j)
+            {
+                cells.push_back({Coord{j, i}, m_grid.get_state(Coord{j, i})});
+            }
     }
     return Structure(cells.begin(), cells.end());
 }
@@ -446,6 +448,18 @@ void GridView::update_gridview()
     m_scene->update();
 }
 
+QGraphicsRectItem *GridView::create_selection_rect(const QRectF &rect)
+{
+    QGraphicsRectItem* item = new QGraphicsRectItem();
+    item->setPen(Qt::NoPen);
+    item->setBrush(QBrush(QColor(220, 220, 220, 200)));
+    item->setRect(rect);
+    m_selection_rects.push_back(item);
+    m_scene->addItem(item);
+
+    return item;
+}
+
 void GridView::copy_selection()
 {
     m_copy_paste_buffer = selected_cells();
@@ -453,13 +467,13 @@ void GridView::copy_selection()
 
 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;
-
     push_history();
 
-    Coord origin = top_left_of_selection();
+    auto scene_pos = m_view->mapToScene(m_view->mapFromGlobal(QCursor::pos()));
+    if (!m_scene->sceneRect().contains(scene_pos))
+        return;
+
+    Coord origin = {scene_pos.toPoint().x(), scene_pos.toPoint().y()};
 
     paste_structure_at(origin, m_copy_paste_buffer);
 }
@@ -468,10 +482,16 @@ void GridView::fill_selection(unsigned state)
 {
     push_history();
 
-    for (auto coord : m_selected_cells)
+    for (const auto& item : m_selection_rects)
     {
-        set_cell_state(coord, state);
+        const auto& rect = item->rect().toRect();
+        for (int i = rect.top(); i <= rect.bottom(); ++i)
+            for (int j = rect.left(); j <= rect.right(); ++j)
+            {
+                set_cell_state(Coord{(int)j, (int)i}, state);
+            }
     }
+
     update_gridview();
 }
 
@@ -481,6 +501,12 @@ void GridView::delete_selection()
     clear_selection();
 }
 
+void GridView::select_all()
+{
+    clear_selection();
+    create_selection_rect(QRect(0, 0, m_width, m_height));
+}
+
 void GridView::paste_structure_at(Coord origin, const Structure &s)
 {
     push_history();
@@ -494,22 +520,6 @@ void GridView::paste_structure_at(Coord origin, const Structure &s)
     update_gridview();
 }
 
-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& rect : m_selection_rects)
-    {
-        if (rect->pos().x() < selection_top_left.x)
-            selection_top_left.x = rect->pos().x();
-        if (rect->pos().y() < selection_top_left.y)
-            selection_top_left.y = rect->pos().y();
-    }
-
-    return selection_top_left;
-}
-
 const QPixmap &GridView::grid_pixmap() const
 {
     return m_grid_pixmap;
@@ -521,11 +531,7 @@ void GridView::handle_rubberband(QRect rubberBandRect, QPointF fromScenePoint, Q
     if (!m_handling_rubberband)
     {
         m_handling_rubberband = true;
-        item = new QGraphicsRectItem();
-        item->setPen(Qt::NoPen);
-        item->setBrush(QBrush(QColor(220, 220, 220, 200)));
-        m_selection_rects.push_back(item);
-        m_scene->addItem(item);
+        item = create_selection_rect();
     }
     else
     {
@@ -537,14 +543,6 @@ void GridView::handle_rubberband(QRect rubberBandRect, QPointF fromScenePoint, Q
     if (rubberBandRect.isNull())
     {
         m_handling_rubberband = false;
-        // Add the cells to the selection
-
-        QRect rect = m_selection_rects.back()->rect().toRect();
-        for (int i = rect.top(); i <= rect.bottom(); ++i)
-            for (int j = rect.left(); j <= rect.right(); ++j)
-            {
-                m_selected_cells.insert(Coord{j, i});
-            }
 
         return;
     }
@@ -583,7 +581,7 @@ void GridView::keyPressEvent(QKeyEvent *event)
         }
         else if (event->key() == Qt::Key_A)
         {
-            // TODO
+            select_all();
         }
         else if (event->key() == Qt::Key_Plus)
         {
-- 
GitLab