From 43baed69dbca70a98258e71c0008636694917cef Mon Sep 17 00:00:00 2001 From: Claveau Joshua Date: Thu, 20 Feb 2020 21:33:26 +0100 Subject: [PATCH] Add QetGraphicsHeaderItem --- .../ViewItem/qetgraphicsheaderitem.cpp | 197 ++++++++++++++++++ .../ViewItem/qetgraphicsheaderitem.h | 60 ++++++ .../ViewItem/qetgraphicstableitem.cpp | 100 ++++----- .../ViewItem/qetgraphicstableitem.h | 8 +- 4 files changed, 306 insertions(+), 59 deletions(-) create mode 100644 sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.cpp create mode 100644 sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.h diff --git a/sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.cpp b/sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.cpp new file mode 100644 index 000000000..4b9c2ba2e --- /dev/null +++ b/sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.cpp @@ -0,0 +1,197 @@ +/* + Copyright 2006-2019 QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "qetgraphicsheaderitem.h" +#include "qabstractitemmodel.h" + +#include +#include + +/** + * @brief QetGraphicsHeaderItem::QetGraphicsHeaderItem + * @param parent + */ +QetGraphicsHeaderItem::QetGraphicsHeaderItem(QGraphicsItem *parent) : + QGraphicsObject(parent) +{ + m_margin = QMargins(5,5,5,5); +} + +/** + * @brief QetGraphicsHeaderItem::setModel + * Set the model presented by this item + * Since QetGraphicsHeaderItem don't take ownership of model, + * if item already have a model, it's your responsability to delete it. + * @param model + */ +void QetGraphicsHeaderItem::setModel(QAbstractItemModel *model) +{ + m_model = model; + reset(); +} + +/** + * @brief QetGraphicsHeaderItem::model + * @return the model that this item is presenting + */ +QAbstractItemModel *QetGraphicsHeaderItem::model() const { + return m_model; +} + +/** + * @brief QetGraphicsHeaderItem::reset + * Reset the internal state of the item + */ +void QetGraphicsHeaderItem::reset() { + setUpMinimumSectionsSize(); +} + +/** + * @brief QetGraphicsHeaderItem::boundingRect + * Reimplemented from QGraphicsObject::boundingRect() const; + * @return + */ +QRectF QetGraphicsHeaderItem::boundingRect() const { + return m_bounding_rect; +} + +/** + * @brief QetGraphicsHeaderItem::paint + * Reimplemented from QGraphicsObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) const; + * @param painter + * @param option + * @param widget + */ +void QetGraphicsHeaderItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option) + Q_UNUSED(widget) + + painter->save(); + + QPen pen; + pen.setWidthF(0.7); + pen.setColor(Qt::black); + + QBrush brush = painter->brush(); + brush.setColor(Qt::lightGray); + brush.setStyle(Qt::SolidPattern); + painter->setBrush(brush); + + painter->setPen(pen); + painter->setFont(m_font); + painter->drawRect(m_current_rect); + + if (!m_model) + { + painter->restore(); + return; + } + + //Draw vertical lines + auto offset= 0; + for(auto size : m_current_sections_width) + { + QPointF p1(offset+size, m_current_rect.top()); + QPointF p2(offset+size, m_current_rect.bottom()); + painter->drawLine(p1, p2); + offset += size; + } + + //Write text of each cell + QPointF top_left(m_margin.left(), m_margin.top()); + for (auto i= 0 ; icolumnCount() ; ++i) + { + QSize size(m_current_sections_width.at(i), m_section_height - m_margin.top() - m_margin.bottom()); + painter->drawText(QRectF(top_left, size), Qt::AlignCenter, m_model->headerData(i, Qt::Horizontal).toString()); + top_left.setX(top_left.x() + size.width()); + } + + painter->restore(); +} + +/** + * @brief QetGraphicsHeaderItem::rect + * @return the current rect of the item aka the size of rectangle painted. + */ +QRect QetGraphicsHeaderItem::rect() const { + return m_current_rect; +} + +void QetGraphicsHeaderItem::resizeSection(int logicalIndex, int size) +{ + if (m_model && logicalIndexcolumnCount()) + { + prepareGeometryChange(); + m_current_sections_width.replace(logicalIndex, size); + m_current_rect.setWidth(std::accumulate(m_current_sections_width.begin(), m_current_sections_width.end(), 0)); + setUpBoundingRect(); + } +} + +/** + * @brief QetGraphicsHeaderItem::sectionSize + * @param logical_index + * @return the width (or height for vertical headers) of the given logicalIndex. + */ +int QetGraphicsHeaderItem::sectionSize(int logical_index) const +{ + if (logical_index>=0 && logical_indexcolumnCount()); + + for (auto i= 0 ; icolumnCount() ; ++i) + { + auto str = m_model->headerData(i, Qt::Horizontal).toString(); + m_sections_minimum_width.replace(i, metrics.boundingRect(str).width() + m_margin.left() + m_margin.right()); + } + + m_current_sections_width = m_sections_minimum_width; + + m_minimum_rect.setRect(0,0, std::accumulate(m_sections_minimum_width.begin(), m_sections_minimum_width.end(), 0), m_section_height); + m_current_rect = m_minimum_rect; + + setUpBoundingRect(); +} + +/** + * @brief QetGraphicsHeaderItem::setUpBoundingRect + * Setup the bounding rect of the item + */ +void QetGraphicsHeaderItem::setUpBoundingRect() { + m_bounding_rect = m_current_rect.adjusted(-10, -10, 10, 10); +} diff --git a/sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.h b/sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.h new file mode 100644 index 000000000..230960939 --- /dev/null +++ b/sources/qetgraphicsitem/ViewItem/qetgraphicsheaderitem.h @@ -0,0 +1,60 @@ +/* + Copyright 2006-2019 QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef QETGRAPHICSHEADERITEM_H +#define QETGRAPHICSHEADERITEM_H + +#include "qetapp.h" + +#include +#include +#include + +class QAbstractItemModel; + +class QetGraphicsHeaderItem : public QGraphicsObject +{ + public: + QetGraphicsHeaderItem(QGraphicsItem *parent = nullptr); + + void setModel(QAbstractItemModel *model); + QAbstractItemModel *model() const; + void reset(); + + virtual QRectF boundingRect() const override; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + QRect rect() const; + void resizeSection(int logicalIndex, int size); + int sectionSize(int logical_index) const; + + private: + void setUpMinimumSectionsSize(); + void setUpBoundingRect(); + + private: + QRectF m_bounding_rect; + QAbstractItemModel *m_model = nullptr; + QFont m_font = QETApp::diagramTextsFont(); + QMargins m_margin; + QVector m_sections_minimum_width, + m_current_sections_width; + int m_section_height=1; + QRect m_minimum_rect, + m_current_rect; +}; + +#endif // QETGRAPHICSHEADERITEM_H diff --git a/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.cpp b/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.cpp index 7b8424005..edfb7e19d 100644 --- a/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.cpp +++ b/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.cpp @@ -17,10 +17,10 @@ */ #include "qetgraphicstableitem.h" #include "diagram.h" +#include "qetgraphicsheaderitem.h" #include #include -#include #include #include #include @@ -46,6 +46,8 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) : connect(this, &QetGraphicsTableItem::xChanged, this, &QetGraphicsTableItem::adjustHandlerPos); connect(this, &QetGraphicsTableItem::yChanged, this, &QetGraphicsTableItem::adjustHandlerPos); + m_header_item = new QetGraphicsHeaderItem(this); + /*******ONLY FOR TEST DURING DEVEL*********/ @@ -60,6 +62,11 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) : model->setItem(row, column, item); } } + model->setHeaderData(0, Qt::Horizontal, "Label"); + model->setHeaderData(1, Qt::Horizontal, "Folio"); + model->setHeaderData(2, Qt::Horizontal, "Fonction"); + model->setHeaderData(3, Qt::Horizontal, "Fabricant"); + model->setHeaderData(4, Qt::Horizontal, "Installation"); this->setModel(model); this->setPos(50,50); } @@ -78,7 +85,11 @@ QetGraphicsTableItem::~QetGraphicsTableItem() void QetGraphicsTableItem::setModel(QAbstractItemModel *model) { m_model = model; - modelReseted(); + reset(); + + m_header_item->setModel(model); + adjustColumnsWidth(); + m_header_item->setPos(0, -m_header_item->rect().height()); } /** @@ -89,6 +100,17 @@ QAbstractItemModel *QetGraphicsTableItem::model() const { return m_model; } +/** + * @brief QetGraphicsTableItem::reset + * Reset the internal state of the item + */ +void QetGraphicsTableItem::reset() +{ + setUpColumnAndRowMinimumSize(); + setUpBoundingRect(); + adjustColumnsWidth(); +} + /** * @brief QetGraphicsTableItem::boundingRect * Reimplemented from QGraphicsObject @@ -128,12 +150,12 @@ void QetGraphicsTableItem::paint(QPainter *painter, const QStyleOptionGraphicsIt //Draw vertical lines auto offset= 0; - for(auto size : m_current_column_width) + for(auto i=0 ; icolumnCount() ; ++i) { - QPointF p1(offset+size, m_current_rect.top()); - QPointF p2(offset+size, m_current_rect.bottom()); + QPointF p1(offset+m_header_item->sectionSize(i), m_current_rect.top()); + QPointF p2(offset+m_header_item->sectionSize(i), m_current_rect.bottom()); painter->drawLine(p1, p2); - offset += size; + offset += m_header_item->sectionSize(i); } //Draw horizontal lines @@ -154,9 +176,9 @@ void QetGraphicsTableItem::paint(QPainter *painter, const QStyleOptionGraphicsIt { //In first iteration the top left X is margin left, in all other iteration the top left X is stored in m_column_size if (j>0) { - top_left.setX(top_left.x() + m_current_column_width.at(j-1)); + top_left.setX(top_left.x() + m_header_item->sectionSize(j-1)); } - QSize size(m_current_column_width.at(j)/* - m_margin.left() - m_margin.right()*/, + QSize size(m_header_item->sectionSize(j), cell_height - m_margin.top() - m_margin.bottom()); painter->drawText(QRectF(top_left, size), Qt::AlignVCenter|Qt::AlignLeft, m_model->index(i, j).data().toString()); } @@ -220,25 +242,6 @@ bool QetGraphicsTableItem::sceneEventFilter(QGraphicsItem *watched, QEvent *even return false; } -/** - * @brief QetGraphicsTableItem::modelReseted - * Called when the model is reseted - */ -void QetGraphicsTableItem::modelReseted() -{ - preProcess(); -} - -/** - * @brief QetGraphicsTableItem::preProcess - * Make all post process needed befor painting - */ -void QetGraphicsTableItem::preProcess() -{ - setUpColumnAndRowMinimumSize(); - setUpBoundingRect(); -} - /** * @brief QetGraphicsTableItem::setUpColumnAndRowMinimumSize * Calcule the minimum row height and the minimum column width for each columns @@ -268,13 +271,10 @@ void QetGraphicsTableItem::setUpColumnAndRowMinimumSize() } //Set the minimum size of the table - m_minimum_rect.setTopLeft(QPoint(0,0)); - m_minimum_rect.setWidth(0); - for (auto cw : m_minimum_column_width) { - m_minimum_rect.setWidth(m_minimum_rect.width()+cw); - } - m_minimum_rect.setHeight(m_row_height*m_model->rowCount()); - m_current_column_width = m_minimum_column_width; + m_minimum_rect.setRect(0, 0, + std::accumulate(m_minimum_column_width.begin(), m_minimum_column_width.end(), 0), + m_row_height*m_model->rowCount()); + m_current_rect = m_minimum_rect; } @@ -311,50 +311,38 @@ void QetGraphicsTableItem::handlerMousePressEvent(QGraphicsSceneMouseEvent *even void QetGraphicsTableItem::handlerMouseMoveEvent(QGraphicsSceneMouseEvent *event) { - QPointF new_handler_pos = event->scenePos(); - if (event->modifiers() != Qt::ControlModifier) { - new_handler_pos = Diagram::snapToGrid(event->scenePos()); - } + auto new_handler_pos = Diagram::snapToGrid(event->scenePos()); QSize size = QRectF(m_current_rect.topLeft(), mapFromScene(new_handler_pos)).size().toSize(); m_handler_item.setPos(mapToScene(std::max(m_minimum_rect.width(), size.width()), std::max(m_minimum_rect.height(), size.height()))); - QRect new_rect(QPoint(0,0), mapFromScene(m_handler_item.scenePos()).toPoint()); + QRect new_rect = QRectF(QPointF(0,0), mapFromScene(m_handler_item.scenePos())).toRect(); if (new_rect != m_current_rect) { + prepareGeometryChange(); m_current_rect = new_rect; + setUpBoundingRect(); adjustColumnsWidth(); } } -void QetGraphicsTableItem::handlerMouseReleaseEvent(QGraphicsSceneMouseEvent *event) -{ +void QetGraphicsTableItem::handlerMouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event) - m_current_rect.setBottomRight(mapFromScene(m_handler_item.scenePos()).toPoint()); } /** * @brief QetGraphicsTableItem::adjustColumnsWidth - * Adjust the size of each column according to the current table width + * Adjust the size of each column according to the current table width by setting the sectionSize of the header item */ void QetGraphicsTableItem::adjustColumnsWidth() { - m_current_column_width = m_minimum_column_width; - - //Get the minimum width of table - auto minimum_width= 0; - for(auto w : m_minimum_column_width) { - minimum_width += w; - } - + auto minimum_width = std::accumulate(m_minimum_column_width.begin(), m_minimum_column_width.end(), 0); auto a = m_current_rect.width() - minimum_width; auto b = a/m_model->columnCount(); - for(auto i= 0 ; iresizeSection(i, m_minimum_column_width.at(i) + b); + } } diff --git a/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.h b/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.h index 23406eaef..462a596b4 100644 --- a/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.h +++ b/sources/qetgraphicsitem/ViewItem/qetgraphicstableitem.h @@ -25,6 +25,7 @@ #include "QetGraphicsItemModeler/qetgraphicshandleritem.h" class QAbstractItemModel; +class QetGraphicsHeaderItem; class QetGraphicsTableItem : public QetGraphicsItem { @@ -34,6 +35,8 @@ class QetGraphicsTableItem : public QetGraphicsItem void setModel(QAbstractItemModel *model); QAbstractItemModel *model() const; + void reset(); + virtual QRectF boundingRect() const override; virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; @@ -44,7 +47,6 @@ class QetGraphicsTableItem : public QetGraphicsItem private: void modelReseted(); - void preProcess(); void setUpColumnAndRowMinimumSize(); void setUpBoundingRect(); void adjustHandlerPos(); @@ -58,8 +60,7 @@ class QetGraphicsTableItem : public QetGraphicsItem QAbstractItemModel *m_model= nullptr; QFont m_font = QETApp::diagramTextsFont(); - QVector m_minimum_column_width, - m_current_column_width; + QVector m_minimum_column_width; int m_row_height; QMargins m_margin; @@ -70,6 +71,7 @@ class QetGraphicsTableItem : public QetGraphicsItem int m_br_margin= 10; QetGraphicsHandlerItem m_handler_item; + QetGraphicsHeaderItem *m_header_item = nullptr; }; #endif // QetGraphicsTableItem_H