mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-01-03 11:00:53 +01:00
Add widget to edit QetGraphicsTableItem and QetGraphicsHeaderItem
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2006-2019 QElectroTech Team
|
||||
Copyright 2006-2020 QElectroTech Team
|
||||
This file is part of QElectroTech.
|
||||
|
||||
QElectroTech is free software: you can redistribute it and/or modify
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "qetgraphicstableitem.h"
|
||||
#include "diagram.h"
|
||||
#include "qetgraphicsheaderitem.h"
|
||||
#include "QPropertyUndoCommand/qpropertyundocommand.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QFontMetrics>
|
||||
@@ -47,12 +48,14 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) :
|
||||
connect(this, &QetGraphicsTableItem::yChanged, this, &QetGraphicsTableItem::adjustHandlerPos);
|
||||
|
||||
m_header_item = new QetGraphicsHeaderItem(this);
|
||||
|
||||
|
||||
connect(m_header_item, &QetGraphicsHeaderItem::sectionResized, this, &QetGraphicsTableItem::headerSectionResized);
|
||||
connect(m_header_item, &QetGraphicsHeaderItem::heightResized, this, [this]() {
|
||||
m_header_item->setPos(0, 0-m_header_item->rect().height());
|
||||
});
|
||||
|
||||
/*******ONLY FOR TEST DURING DEVEL*********/
|
||||
auto model = new QStandardItemModel(this);
|
||||
int r = 10;
|
||||
int r = 20;
|
||||
int c = 5;
|
||||
|
||||
for (int row = 0; row < r; ++row)
|
||||
@@ -62,6 +65,10 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) :
|
||||
model->setItem(row, column, item);
|
||||
}
|
||||
}
|
||||
model->setData(model->index(0,0), Qt::AlignLeft, Qt::TextAlignmentRole);
|
||||
model->setData(model->index(0,0), QETApp::diagramTextsFont(), Qt::FontRole);
|
||||
model->setHeaderData(0, Qt::Horizontal, Qt::AlignHCenter, Qt::TextAlignmentRole);
|
||||
model->setHeaderData(0, Qt::Horizontal, QETApp::diagramTextsFont(), Qt::FontRole);
|
||||
model->setHeaderData(0, Qt::Horizontal, "Label");
|
||||
model->setHeaderData(1, Qt::Horizontal, "Folio");
|
||||
model->setHeaderData(2, Qt::Horizontal, "Fonction");
|
||||
@@ -69,11 +76,11 @@ QetGraphicsTableItem::QetGraphicsTableItem(QGraphicsItem *parent) :
|
||||
model->setHeaderData(4, Qt::Horizontal, "Installation");
|
||||
this->setModel(model);
|
||||
this->setPos(50,50);
|
||||
/******************************************/
|
||||
}
|
||||
|
||||
QetGraphicsTableItem::~QetGraphicsTableItem()
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::setModel
|
||||
@@ -84,12 +91,17 @@ QetGraphicsTableItem::~QetGraphicsTableItem()
|
||||
*/
|
||||
void QetGraphicsTableItem::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
if (m_model) {
|
||||
disconnect(m_model, &QAbstractItemModel::dataChanged, this, &QetGraphicsTableItem::dataChanged);
|
||||
}
|
||||
m_model = model;
|
||||
reset();
|
||||
|
||||
m_header_item->setModel(model);
|
||||
adjustColumnsWidth();
|
||||
|
||||
setUpColumnAndRowMinimumSize();
|
||||
adjustSize();
|
||||
|
||||
m_header_item->setPos(0, -m_header_item->rect().height());
|
||||
connect(m_model, &QAbstractItemModel::dataChanged, this, &QetGraphicsTableItem::dataChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,17 +112,6 @@ 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
|
||||
@@ -138,9 +139,9 @@ void QetGraphicsTableItem::paint(QPainter *painter, const QStyleOptionGraphicsIt
|
||||
pen.setWidthF(0.7);
|
||||
pen.setColor(Qt::black);
|
||||
painter->setPen(pen);
|
||||
painter->setFont(m_font);
|
||||
painter->setFont(m_model->data(model()->index(0,0), Qt::FontRole).value<QFont>());
|
||||
|
||||
painter->drawRect(m_current_rect);
|
||||
painter->drawRect(0,0, m_header_item->rect().width(), m_current_size.height());
|
||||
|
||||
if(!m_model)
|
||||
{
|
||||
@@ -152,25 +153,25 @@ void QetGraphicsTableItem::paint(QPainter *painter, const QStyleOptionGraphicsIt
|
||||
auto offset= 0;
|
||||
for(auto i=0 ; i<m_model->columnCount() ; ++i)
|
||||
{
|
||||
QPointF p1(offset+m_header_item->sectionSize(i), m_current_rect.top());
|
||||
QPointF p2(offset+m_header_item->sectionSize(i), m_current_rect.bottom());
|
||||
QPointF p1(offset+m_header_item->sectionSize(i), 0);
|
||||
QPointF p2(offset+m_header_item->sectionSize(i), m_current_size.height());
|
||||
painter->drawLine(p1, p2);
|
||||
offset += m_header_item->sectionSize(i);
|
||||
}
|
||||
|
||||
//Draw horizontal lines
|
||||
auto cell_height = m_current_rect.height()/m_model->rowCount();
|
||||
auto cell_height = static_cast<double>(m_current_size.height())/static_cast<double>(m_model->rowCount());
|
||||
for(auto i= 1 ; i-1<m_model->rowCount() ; ++i)
|
||||
{
|
||||
QPointF p1(m_current_rect.left(), cell_height*i);
|
||||
QPointF p2(m_current_rect.right(), cell_height*i);
|
||||
QPointF p1(m_header_item->rect().left(), cell_height*i);
|
||||
QPointF p2(m_header_item->rect().right(), cell_height*i);
|
||||
painter->drawLine(p1, p2);
|
||||
}
|
||||
|
||||
//Write text of each cell
|
||||
for (auto i= 0 ; i<m_model->rowCount() ; ++i)
|
||||
{
|
||||
QPointF top_left(m_margin.left(), i==0? 0 : cell_height*i);
|
||||
QPointF top_left(m_margin.left(), i==0? m_margin.top() : cell_height*i + m_margin.top());
|
||||
|
||||
for(auto j= 0 ; j<m_model->columnCount() ; ++j)
|
||||
{
|
||||
@@ -178,15 +179,71 @@ void QetGraphicsTableItem::paint(QPainter *painter, const QStyleOptionGraphicsIt
|
||||
if (j>0) {
|
||||
top_left.setX(top_left.x() + m_header_item->sectionSize(j-1));
|
||||
}
|
||||
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());
|
||||
QSize size(m_header_item->sectionSize(j) - m_margin.left() - m_margin.right(),
|
||||
static_cast<int>(cell_height) - m_margin.top() - m_margin.bottom());
|
||||
painter->drawText(QRectF(top_left, size),
|
||||
m_model->data(m_model->index(0,0), Qt::TextAlignmentRole).toInt(),
|
||||
m_model->index(i, j).data().toString());
|
||||
}
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::setMargins
|
||||
* @param margins
|
||||
*/
|
||||
void QetGraphicsTableItem::setMargins(const QMargins &margins)
|
||||
{
|
||||
m_margin = margins;
|
||||
setUpColumnAndRowMinimumSize();
|
||||
adjustSize();
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::setSize
|
||||
* Set the current size of the table to @size
|
||||
* @param size
|
||||
*/
|
||||
void QetGraphicsTableItem::setSize(const QSize &size)
|
||||
{
|
||||
auto new_size = size;
|
||||
if (new_size.width() < minimumSize().width()) {
|
||||
new_size.setWidth(minimumSize().width());
|
||||
}
|
||||
if (new_size.height() < minimumSize().height()) {
|
||||
new_size.setHeight(minimumSize().height());
|
||||
}
|
||||
|
||||
prepareGeometryChange();
|
||||
m_current_size = new_size;
|
||||
adjustColumnsWidth();
|
||||
setUpBoundingRect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::size
|
||||
* @return The current size of the table
|
||||
*/
|
||||
QSize QetGraphicsTableItem::size() const
|
||||
{
|
||||
QSize size_(m_header_item->rect().width(), m_current_size.height());
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::minimumSize
|
||||
* @return the minimum size the table can be
|
||||
* The returned size take care of the table's minimum width, but also the header item's minimum width
|
||||
*/
|
||||
QSize QetGraphicsTableItem::minimumSize() const
|
||||
{
|
||||
QSize s(std::accumulate(m_minimum_column_width.begin(), m_minimum_column_width.end(), 0), m_minimum_row_height*m_model->rowCount());
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::hoverEnterEvent
|
||||
* Reimplemented from QetGraphicsItem
|
||||
@@ -245,6 +302,7 @@ bool QetGraphicsTableItem::sceneEventFilter(QGraphicsItem *watched, QEvent *even
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::setUpColumnAndRowMinimumSize
|
||||
* Calcule the minimum row height and the minimum column width for each columns
|
||||
* this function doesn't change the geometry of the table.
|
||||
*/
|
||||
void QetGraphicsTableItem::setUpColumnAndRowMinimumSize()
|
||||
{
|
||||
@@ -252,48 +310,40 @@ void QetGraphicsTableItem::setUpColumnAndRowMinimumSize()
|
||||
return;
|
||||
}
|
||||
|
||||
QFontMetrics metrics(m_font);
|
||||
QFontMetrics metrics(m_model->data(model()->index(0,0), Qt::FontRole).value<QFont>());
|
||||
//Set the height of row;
|
||||
m_row_height = metrics.boundingRect("HEIGHT TEST").height() + m_margin.top() + m_margin.bottom();
|
||||
m_minimum_row_height = metrics.boundingRect("HEIGHT TEST").height() + m_margin.top() + m_margin.bottom();
|
||||
|
||||
m_minimum_column_width.clear();
|
||||
m_minimum_column_width.resize(m_model->columnCount());
|
||||
m_minimum_column_width = m_header_item->minimumSectionWidth();
|
||||
|
||||
//Get the maximum width of each columns
|
||||
for (auto i= 0 ; i<m_model->rowCount() ; ++i)
|
||||
for (auto row= 0 ; row<m_model->rowCount() ; ++row)
|
||||
{
|
||||
for(auto j= 0 ; j<m_model->columnCount() ; ++j)
|
||||
for(auto col= 0 ; col<m_model->columnCount() ; ++col)
|
||||
{
|
||||
auto index = m_model->index(i, j);
|
||||
auto index = m_model->index(row, col);
|
||||
auto width = metrics.boundingRect(index.data().toString()).width();
|
||||
m_minimum_column_width.replace(j, std::max(m_minimum_column_width.at(j), width+m_margin.left() + m_margin.right()));
|
||||
m_minimum_column_width.replace(col, std::max(m_minimum_column_width.at(col), width + m_margin.left() + m_margin.right()));
|
||||
}
|
||||
}
|
||||
|
||||
//Set the minimum size of the table
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::setUpBoundingRect
|
||||
*/
|
||||
void QetGraphicsTableItem::setUpBoundingRect() {
|
||||
m_bounding_rect = m_current_rect.adjusted(-m_br_margin, -m_br_margin, m_br_margin, m_br_margin);
|
||||
void QetGraphicsTableItem::setUpBoundingRect()
|
||||
{
|
||||
QSize header_size = m_header_item->rect().size();
|
||||
QRect rect(0, -header_size.height(), header_size.width(), m_current_size.height() + header_size.height());
|
||||
m_bounding_rect = rect.adjusted(-m_br_margin, -m_br_margin, m_br_margin, m_br_margin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::adjustHandlerPos
|
||||
* Adjust the pos of the handler item
|
||||
*/
|
||||
void QetGraphicsTableItem::adjustHandlerPos()
|
||||
{
|
||||
if(m_handler_item.scene()) {
|
||||
m_handler_item.setPos(mapToScene(m_current_rect.bottomRight()));
|
||||
}
|
||||
void QetGraphicsTableItem::adjustHandlerPos() {
|
||||
m_handler_item.setPos(mapToScene(QRect(QPoint(0,0), size()).bottomRight()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,31 +355,41 @@ void QetGraphicsTableItem::setUpHandler()
|
||||
m_handler_item.setZValue(this->zValue() + 1);
|
||||
}
|
||||
|
||||
void QetGraphicsTableItem::handlerMousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
void QetGraphicsTableItem::handlerMousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
m_old_size = size();
|
||||
//User start to resize the table, disconnect the signal to avoid double paint.
|
||||
disconnect(m_header_item, &QetGraphicsHeaderItem::sectionResized, this, &QetGraphicsTableItem::headerSectionResized);
|
||||
}
|
||||
|
||||
void QetGraphicsTableItem::handlerMouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
auto new_handler_pos = Diagram::snapToGrid(event->scenePos());
|
||||
QSize size = QRectF(m_current_rect.topLeft(), mapFromScene(new_handler_pos)).size().toSize();
|
||||
QSize size_ = QRectF(QPointF(0,0), 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())));
|
||||
QPoint new_pos(std::max(minimumSize().width(), size_.width()),
|
||||
std::max(minimumSize().height(), size_.height()));
|
||||
m_handler_item.setPos(mapToScene(new_pos));
|
||||
|
||||
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();
|
||||
QSize new_size(new_pos.x(), new_pos.y());
|
||||
if (new_size != size()) {
|
||||
setSize(new_size);
|
||||
}
|
||||
}
|
||||
|
||||
void QetGraphicsTableItem::handlerMouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
void QetGraphicsTableItem::handlerMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
if (diagram())
|
||||
{
|
||||
auto undo = new QPropertyUndoCommand(this, "size", m_old_size, size());
|
||||
undo->setAnimated();
|
||||
undo->setText(tr("Modifier la géometrie d'un tableau"));
|
||||
diagram()->undoStack().push(undo);
|
||||
}
|
||||
//User finish to resize the table, we can reconnect now
|
||||
connect(m_header_item, &QetGraphicsHeaderItem::sectionResized, this, &QetGraphicsTableItem::headerSectionResized);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -338,11 +398,62 @@ void QetGraphicsTableItem::handlerMouseReleaseEvent(QGraphicsSceneMouseEvent *ev
|
||||
*/
|
||||
void QetGraphicsTableItem::adjustColumnsWidth()
|
||||
{
|
||||
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 a = m_current_size.width() - minimumSize().width();
|
||||
auto b = a/m_model->columnCount();
|
||||
|
||||
for(auto i= 0 ; i<m_minimum_column_width.size() ; ++i) {
|
||||
m_header_item->resizeSection(i, m_minimum_column_width.at(i) + b);
|
||||
for(auto i= 0 ; i<m_model->columnCount() ; ++i) {
|
||||
m_header_item->resizeSection(i, std::max(m_minimum_column_width.at(i), m_header_item->minimumSectionWidth().at(i)) + b);
|
||||
}
|
||||
}
|
||||
|
||||
void QetGraphicsTableItem::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
|
||||
{
|
||||
Q_UNUSED(topLeft)
|
||||
Q_UNUSED(bottomRight)
|
||||
Q_UNUSED(roles)
|
||||
|
||||
auto size_ = size();
|
||||
setUpColumnAndRowMinimumSize();
|
||||
adjustSize();
|
||||
setSize(size_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::headerSectionResized
|
||||
* Connected to the header signal QetGraphicsTableItem sectionResized
|
||||
*/
|
||||
void QetGraphicsTableItem::headerSectionResized()
|
||||
{
|
||||
auto header_size = m_header_item->rect().size();
|
||||
auto size_ = size();
|
||||
size_.setWidth(header_size.width());
|
||||
|
||||
m_current_size = size_;
|
||||
prepareGeometryChange();
|
||||
setUpBoundingRect();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QetGraphicsTableItem::adjustSize
|
||||
* If needed, this function resize the current height and width of table
|
||||
* according to there minimum
|
||||
*/
|
||||
void QetGraphicsTableItem::adjustSize()
|
||||
{
|
||||
if (m_current_size.height() < minimumSize().height())
|
||||
{
|
||||
prepareGeometryChange();
|
||||
m_current_size.setHeight(minimumSize().height());
|
||||
setUpBoundingRect();
|
||||
update();
|
||||
}
|
||||
|
||||
if (m_current_size.width() < minimumSize().width())
|
||||
{
|
||||
prepareGeometryChange();
|
||||
m_current_size.setWidth(minimumSize().width());
|
||||
adjustColumnsWidth();
|
||||
setUpBoundingRect();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user