0
0
mirror of https://github.com/fralx/LimeReport.git synced 2024-12-24 00:33:02 +03:00
LimeReport/limereport/items/lrabstractlayout.cpp

397 lines
12 KiB
C++
Raw Permalink Normal View History

2018-06-21 14:29:00 +03:00
#include "lrabstractlayout.h"
namespace LimeReport {
AbstractLayout::AbstractLayout(QString xmlTag, QObject* owner, QGraphicsItem* parent):
LayoutDesignIntf(xmlTag, owner, parent),
m_isRelocating(false),
m_layoutType(Layout),
m_hideEmptyItems(false),
m_layoutSpacing(0)
2018-06-21 14:29:00 +03:00
{
setPossibleResizeDirectionFlags(AllDirections);
m_layoutMarker = new LayoutMarker(this);
m_layoutMarker->setParentItem(this);
m_layoutMarker->setColor(Qt::red);
m_layoutMarker->setHeight(height());
m_layoutMarker->setZValue(1);
}
AbstractLayout::~AbstractLayout()
{
if (m_layoutMarker) {
delete m_layoutMarker;
m_layoutMarker = 0;
2018-06-21 14:29:00 +03:00
}
}
QList<BaseDesignIntf*>& AbstractLayout::layoutsChildren() { return m_children; }
2018-06-21 14:29:00 +03:00
bool AbstractLayout::isRelocating() const { return m_isRelocating; }
2018-06-21 14:29:00 +03:00
void AbstractLayout::setIsRelocating(bool isRelocating) { m_isRelocating = isRelocating; }
2018-06-21 14:29:00 +03:00
AbstractLayout::LayoutType AbstractLayout::layoutType() const { return m_layoutType; }
2018-06-21 14:29:00 +03:00
void AbstractLayout::setLayoutType(const LayoutType& layoutType) { m_layoutType = layoutType; }
2018-06-21 14:29:00 +03:00
void AbstractLayout::addChild(BaseDesignIntf* item, bool updateSize)
{
if (updateSize)
placeItemInLayout(item);
2018-06-21 14:29:00 +03:00
m_children.append(item);
item->setParentItem(this);
item->setParent(this);
item->setFixedPos(true);
item->setPossibleResizeDirectionFlags(ResizeRight | ResizeBottom);
2022-02-06 17:14:04 +03:00
connectToLayout(item);
2018-06-21 14:29:00 +03:00
if (updateSize) {
2018-06-21 14:29:00 +03:00
relocateChildren();
updateLayoutSize();
}
}
void AbstractLayout::removeChild(BaseDesignIntf* item)
2022-02-06 17:14:04 +03:00
{
if (!item) {
return;
}
m_children.removeAll(item);
disconnectFromLayout(item);
}
2018-06-21 14:29:00 +03:00
void AbstractLayout::restoreChild(BaseDesignIntf* item)
{
if (m_children.contains(item))
return;
m_isRelocating = true;
2018-06-21 14:29:00 +03:00
insertItemInLayout(item);
2022-02-06 17:14:04 +03:00
connectToLayout(item);
2018-06-21 14:29:00 +03:00
item->setFixedPos(true);
item->setPossibleResizeDirectionFlags(ResizeRight | ResizeBottom);
item->setParent(this);
item->setParentItem(this);
updateLayoutSize();
m_isRelocating = false;
2018-06-21 14:29:00 +03:00
}
bool AbstractLayout::isEmpty() const
{
bool isEmpty = true;
bool allItemsIsText = true;
foreach (QGraphicsItem* qgItem, childItems()) {
ContentItemDesignIntf* item = dynamic_cast<ContentItemDesignIntf*>(qgItem);
if (item && !item->content().isEmpty())
isEmpty = false;
2018-06-21 14:29:00 +03:00
if (!item && dynamic_cast<BaseDesignIntf*>(qgItem))
allItemsIsText = false;
}
return (isEmpty && allItemsIsText);
}
void AbstractLayout::paintChild(BaseDesignIntf* child, QPointF parentPos, QPainter* painter)
2019-01-15 13:59:00 +03:00
{
if (!child->childBaseItems().isEmpty()) {
2019-01-15 13:59:00 +03:00
foreach (BaseDesignIntf* item, child->childBaseItems()) {
paintChild(item, child->pos(), painter);
2019-01-15 13:59:00 +03:00
}
}
painter->drawRect(QRectF(parentPos.x() + child->pos().x(), parentPos.y() + child->pos().y(),
child->rect().bottomRight().rx(), child->rect().bottomRight().ry()));
2019-01-15 13:59:00 +03:00
}
void AbstractLayout::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
QWidget* widget)
2018-06-21 14:29:00 +03:00
{
if (isSelected()) {
2019-01-15 13:59:00 +03:00
painter->save();
painter->setPen(Qt::red);
foreach (BaseDesignIntf* item, m_children) {
paintChild(item, QPointF(0, 0), painter);
2018-06-21 14:29:00 +03:00
}
2019-01-15 13:59:00 +03:00
painter->restore();
2018-06-21 14:29:00 +03:00
}
2019-01-15 13:59:00 +03:00
LayoutDesignIntf::paint(painter, option, widget);
2018-06-21 14:29:00 +03:00
}
int AbstractLayout::childrenCount() { return m_children.size(); }
2018-06-21 14:29:00 +03:00
void AbstractLayout::beforeDelete()
{
#ifdef HAVE_QT5
foreach (QObject* item, children()) {
2018-06-21 14:29:00 +03:00
#else
foreach (QObject* item, QObject::children()) {
2018-06-21 14:29:00 +03:00
#endif
BaseDesignIntf* bi = dynamic_cast<BaseDesignIntf*>(item);
2018-06-21 14:29:00 +03:00
if (bi) {
2019-10-16 22:55:35 +03:00
bi->disconnect(this);
2018-06-21 14:29:00 +03:00
bi->setParentItem(parentItem());
bi->setParent(parent());
bi->setVisible(true);
bi->setPos(mapToParent(bi->pos()));
bi->setFixedPos(false);
bi->setPossibleResizeDirectionFlags(AllDirections);
}
}
m_children.clear();
}
void AbstractLayout::childAddedEvent(BaseDesignIntf* child) { addChild(child, false); }
2018-06-21 14:29:00 +03:00
void AbstractLayout::geometryChangedEvent(QRectF newRect, QRectF)
{
layoutMarker()->setHeight(newRect.height());
relocateChildren();
if (!isRelocating()) {
2018-06-21 14:29:00 +03:00
divideSpace();
}
}
void AbstractLayout::initMode(BaseDesignIntf::ItemMode mode)
{
BaseDesignIntf::initMode(mode);
if ((mode == PreviewMode) || (mode == PrintMode)) {
2018-06-21 14:29:00 +03:00
layoutMarker()->setVisible(false);
} else {
layoutMarker()->setVisible(true);
}
}
void AbstractLayout::setBorderLinesFlags(BaseDesignIntf::BorderLines flags)
{
BaseDesignIntf::setBorderLinesFlags(flags);
if (flags != 0)
2018-06-21 14:29:00 +03:00
relocateChildren();
}
void AbstractLayout::collectionLoadFinished(const QString& collectionName)
{
ItemDesignIntf::collectionLoadFinished(collectionName);
if (collectionName.compare("children", Qt::CaseInsensitive) == 0) {
2018-06-21 14:29:00 +03:00
#ifdef HAVE_QT5
foreach (QObject* obj, children()) {
2018-06-21 14:29:00 +03:00
#else
foreach (QObject* obj, QObject::children()) {
2018-06-21 14:29:00 +03:00
#endif
BaseDesignIntf* item = dynamic_cast<BaseDesignIntf*>(obj);
if (item) {
addChild(item, false);
2018-06-21 14:29:00 +03:00
}
}
}
}
void AbstractLayout::objectLoadFinished()
{
layoutMarker()->setHeight(height());
LayoutDesignIntf::objectLoadFinished();
}
bool AbstractLayout::isNeedUpdateSize(RenderPass pass) const
{
2019-02-10 04:50:40 +03:00
Q_UNUSED(pass)
return true;
2018-06-21 14:29:00 +03:00
}
QVariant AbstractLayout::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged) {
2018-06-21 14:29:00 +03:00
setIsRelocating(true);
foreach (BaseDesignIntf* item, layoutsChildren()) {
2018-06-21 14:29:00 +03:00
item->setVisible(!value.toBool());
}
setIsRelocating(false);
}
return LayoutDesignIntf::itemChange(change, value);
}
void AbstractLayout::updateItemSize(DataSourceManager* dataManager, RenderPass pass, int maxHeight)
{
setIsRelocating(true);
ItemDesignIntf::updateItemSize(dataManager, pass, maxHeight);
foreach (QGraphicsItem* child, childItems()) {
2018-06-21 14:29:00 +03:00
BaseDesignIntf* item = dynamic_cast<BaseDesignIntf*>(child);
2019-02-10 04:50:40 +03:00
if (item && item->isNeedUpdateSize(pass))
item->updateItemSize(dataManager, pass, maxHeight);
2018-06-21 14:29:00 +03:00
}
updateLayoutSize();
relocateChildren();
setIsRelocating(false);
BaseDesignIntf::updateItemSize(dataManager, pass, maxHeight);
}
void AbstractLayout::rebuildChildrenIfNeeded()
{
if (layoutsChildren().count() < childItems().size() - 1) {
2019-02-02 00:28:30 +03:00
layoutsChildren().clear();
foreach (BaseDesignIntf* childItem, childBaseItems()) {
layoutsChildren().append(childItem);
}
sortChildren();
}
}
void AbstractLayout::connectToLayout(BaseDesignIntf* item)
{
connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(slotOnChildDestroy(QObject*)));
connect(item, SIGNAL(geometryChanged(QObject*, QRectF, QRectF)), this,
SLOT(slotOnChildGeometryChanged(QObject*, QRectF, QRectF)));
connect(item, SIGNAL(itemVisibleHasChanged(BaseDesignIntf*)), this,
SLOT(slotOnChildVisibleHasChanged(BaseDesignIntf*)));
connect(item, SIGNAL(itemSelectedHasBeenChanged(BaseDesignIntf*, bool)), this,
SLOT(slotOnChildSelectionHasChanged(BaseDesignIntf*, bool)));
connect(item, SIGNAL(itemAlignChanged(BaseDesignIntf*, const ItemAlign&, const ItemAlign&)),
this,
SLOT(slotOnChildItemAlignChanged(BaseDesignIntf*, const ItemAlign&, const ItemAlign&)));
2022-02-06 17:14:04 +03:00
}
void AbstractLayout::disconnectFromLayout(BaseDesignIntf* item)
2022-02-06 17:14:04 +03:00
{
disconnect(item, SIGNAL(destroyed(QObject*)), this, SLOT(slotOnChildDestroy(QObject*)));
disconnect(item, SIGNAL(geometryChanged(QObject*, QRectF, QRectF)), this,
SLOT(slotOnChildGeometryChanged(QObject*, QRectF, QRectF)));
disconnect(item, SIGNAL(itemVisibleHasChanged(BaseDesignIntf*)), this,
SLOT(slotOnChildVisibleHasChanged(BaseDesignIntf*)));
disconnect(item, SIGNAL(itemSelectedHasBeenChanged(BaseDesignIntf*, bool)), this,
SLOT(slotOnChildSelectionHasChanged(BaseDesignIntf*, bool)));
2022-02-06 17:14:04 +03:00
disconnect(
item, SIGNAL(itemAlignChanged(BaseDesignIntf*, const ItemAlign&, const ItemAlign&)), this,
SLOT(slotOnChildItemAlignChanged(BaseDesignIntf*, const ItemAlign&, const ItemAlign&)));
}
BaseDesignIntf* AbstractLayout::findNext(BaseDesignIntf* item)
2019-02-02 00:28:30 +03:00
{
rebuildChildrenIfNeeded();
for (int i = 0; i < layoutsChildren().count(); ++i) {
if (layoutsChildren()[i] == item && layoutsChildren().size() > i + 1) {
return layoutsChildren()[i + 1];
}
2019-02-02 00:28:30 +03:00
}
return 0;
}
BaseDesignIntf* AbstractLayout::findPrior(BaseDesignIntf* item)
2019-02-02 00:28:30 +03:00
{
rebuildChildrenIfNeeded();
for (int i = 0; i < layoutsChildren().count(); ++i) {
if (layoutsChildren()[i] == item && i != 0) {
return layoutsChildren()[i - 1];
}
2019-02-02 00:28:30 +03:00
}
return 0;
}
void AbstractLayout::insertItemInLayout(BaseDesignIntf* item)
{
2024-07-25 18:32:30 +03:00
bool inserted = false;
for (int i = 0; i < layoutsChildren().length(); ++i) {
2024-07-25 18:32:30 +03:00
BaseDesignIntf* child = layoutsChildren()[i];
if (child->pos() == item->pos()) {
2024-07-25 18:32:30 +03:00
layoutsChildren().insert(i, item);
inserted = true;
break;
}
}
if (!inserted)
layoutsChildren().append(item);
2024-07-25 18:32:30 +03:00
}
2018-06-21 14:29:00 +03:00
void AbstractLayout::slotOnChildDestroy(QObject* child)
{
m_children.removeAll(static_cast<BaseDesignIntf*>(child));
if (m_children.count() < 2 && !static_cast<LayoutDesignIntf*>(child)) {
2018-06-21 14:29:00 +03:00
beforeDelete();
} else {
relocateChildren();
updateLayoutSize();
}
}
void AbstractLayout::slotOnChildGeometryChanged(QObject* item, QRectF newGeometry,
QRectF oldGeometry)
2018-06-21 14:29:00 +03:00
{
if (!m_isRelocating && !isLoading()) {
if (m_layoutType == Layout) {
2018-06-21 14:29:00 +03:00
relocateChildren();
updateLayoutSize();
} else {
m_isRelocating = true;
qreal delta = newGeometry.width() - oldGeometry.width();
2018-06-21 14:29:00 +03:00
BaseDesignIntf* resizingItem = findNext(dynamic_cast<BaseDesignIntf*>(item));
if (resizingItem) {
resizingItem->setWidth(resizingItem->width() - delta);
resizingItem->setPos(resizingItem->pos().x() + delta, resizingItem->pos().y());
2018-06-21 14:29:00 +03:00
}
updateLayoutSize();
m_isRelocating = false;
}
}
}
void AbstractLayout::slotOnChildItemAlignChanged(BaseDesignIntf* item, const ItemAlign&,
const ItemAlign&)
2018-06-21 14:29:00 +03:00
{
item->setPossibleResizeDirectionFlags(ResizeBottom | ResizeRight);
}
void AbstractLayout::slotOnChildVisibleHasChanged(BaseDesignIntf*)
{
relocateChildren();
if (m_layoutType == Table && !m_isRelocating) {
2018-06-21 14:29:00 +03:00
divideSpace();
}
}
void AbstractLayout::slotOnChildSelectionHasChanged(BaseDesignIntf* item, bool value)
{
item->setZValue(value ? item->zValue() + 1 : item->zValue() - 1);
2018-06-21 14:29:00 +03:00
}
int AbstractLayout::layoutSpacing() const { return m_layoutSpacing; }
void AbstractLayout::setLayoutSpacing(int layoutSpacing)
{
if (m_layoutSpacing != layoutSpacing) {
int oldValue = m_layoutSpacing;
m_layoutSpacing = layoutSpacing;
if (!isLoading()) {
int delta = (m_layoutSpacing - oldValue) * (m_children.count() - 1);
2019-02-10 04:50:40 +03:00
notify("layoutSpacing", oldValue, m_layoutSpacing);
setWidth(width() + delta);
}
relocateChildren();
}
}
bool AbstractLayout::hideEmptyItems() const { return m_hideEmptyItems; }
2018-06-21 14:29:00 +03:00
void AbstractLayout::setHideEmptyItems(bool hideEmptyItems)
{
m_hideEmptyItems = hideEmptyItems;
if (m_hideEmptyItems != hideEmptyItems) {
2018-06-21 14:29:00 +03:00
m_hideEmptyItems = hideEmptyItems;
notify("hideEmptyItems", !m_hideEmptyItems, m_hideEmptyItems);
}
}
2019-02-04 19:40:29 +03:00
QObject* AbstractLayout::at(int index)
2019-02-02 00:28:30 +03:00
{
rebuildChildrenIfNeeded();
if (layoutsChildren().size() > index)
return layoutsChildren()[index];
2019-02-02 00:28:30 +03:00
return 0;
}
LayoutMarker* AbstractLayout::layoutMarker() const { return m_layoutMarker; }
2018-06-21 14:29:00 +03:00
} // namespace LimeReport