/***************************************************************************
* This file is part of the Lime Report project *
* Copyright (C) 2015 by Alexander Arin *
* arin_a@bk.ru *
* *
** GNU General Public License Usage **
* *
* This library 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 3 of the License, or *
* (at your option) any later version. *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see . *
* *
** GNU Lesser General Public License **
* *
* This library is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of the *
* License, or (at your option) any later version. *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library. *
* If not, see . *
* *
* This library 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. *
****************************************************************************/
#include "lrhorizontallayout.h"
#include "lrdesignelementsfactory.h"
#include
#include
#include
#include
#include "lrbasedesignintf.h"
const QString xmlTag = "HLayout";
namespace {
LimeReport::BaseDesignIntf *createHLayout(QObject *owner, LimeReport::BaseDesignIntf *parent)
{
return new LimeReport::HorizontalLayout(owner, parent);
}
bool registred = LimeReport::DesignElementsFactory::instance().registerCreator(
xmlTag,
LimeReport::ItemAttribs(QObject::tr("HLayout"), LimeReport::bandTAG),
createHLayout
);
}
namespace LimeReport {
bool lessThen(BaseDesignIntf *c1, BaseDesignIntf* c2){
return c1->pos().x()pos().x();
}
HorizontalLayout::HorizontalLayout(QObject *owner, QGraphicsItem *parent)
: LayoutDesignIntf(xmlTag, owner, parent),m_isRelocating(false)
{
setPosibleResizeDirectionFlags(ResizeBottom);
m_layoutMarker = new LayoutMarker(this);
m_layoutMarker->setParentItem(this);
m_layoutMarker->setColor(Qt::red);
m_layoutMarker->setHeight(height());
m_layoutMarker->setZValue(1);
}
HorizontalLayout::~HorizontalLayout()
{
if (m_layoutMarker) {
delete m_layoutMarker; m_layoutMarker=0;
}
}
BaseDesignIntf *HorizontalLayout::createSameTypeItem(QObject *owner, QGraphicsItem *parent)
{
return new LimeReport::HorizontalLayout(owner, parent);
}
void HorizontalLayout::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event)
// if ((itemMode() & LayoutEditMode) || isSelected()){
// setChildVisibility(false);
// }
}
void HorizontalLayout::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event)
// setChildVisibility(true);
}
void HorizontalLayout::geometryChangedEvent(QRectF newRect, QRectF )
{
m_layoutMarker->setHeight(newRect.height());
relocateChildren();
}
void HorizontalLayout::setChildVisibility(bool value){
foreach(QGraphicsItem* child,childItems()){
BaseDesignIntf* item = dynamic_cast(child);
if(item)
item->setVisible(value);
}
}
int HorizontalLayout::childrenCount()
{
return m_children.size();
}
void HorizontalLayout::initMode(BaseDesignIntf::ItemMode mode)
{
BaseDesignIntf::initMode(mode);
if ((mode==PreviewMode)||(mode==PrintMode)){
m_layoutMarker->setVisible(false);
} else {
m_layoutMarker->setVisible(true);
}
}
bool HorizontalLayout::canBeSplitted(int height) const
{
foreach(QGraphicsItem* qgItem,childItems()){
BaseDesignIntf* item=dynamic_cast(qgItem);
if (item)
if (!item->canBeSplitted(height-item->pos().y())) return false;
}
return true;
}
BaseDesignIntf *HorizontalLayout::cloneUpperPart(int height, QObject *owner, QGraphicsItem *parent)
{
HorizontalLayout* upperPart = dynamic_cast(createSameTypeItem(owner,parent));
upperPart->initFromItem(this);
qreal maxHeight = 0;
foreach(BaseDesignIntf* item,childBaseItems()){
if ((item->geometry().top()geometry().bottom()>height)){
int sliceHeight = height-item->geometry().top();
if (item->canBeSplitted(sliceHeight)){
BaseDesignIntf* slicedPart = item->cloneUpperPart(sliceHeight,upperPart,upperPart);
if (maxHeightheight()) maxHeight = slicedPart->height();
} else {
item->cloneEmpty(sliceHeight,upperPart,upperPart);
item->setPos(item->pos().x(),item->pos().y()+((height+1)-item->geometry().top()));
}
}
}
foreach(BaseDesignIntf* item, upperPart->childBaseItems()){
item->setHeight((maxHeightsetHeight(height);
return upperPart;
}
BaseDesignIntf *HorizontalLayout::cloneBottomPart(int height, QObject *owner, QGraphicsItem *parent)
{
qreal maxHeight = 0;
HorizontalLayout* bottomPart = dynamic_cast(createSameTypeItem(owner,parent));
bottomPart->initFromItem(this);
foreach(BaseDesignIntf* item,childBaseItems()){
if ((item->geometry().top()geometry().bottom()>height)){
BaseDesignIntf* tmpItem=item->cloneBottomPart(height,bottomPart,bottomPart);
tmpItem->setPos(tmpItem->pos().x(),0);
if (maxHeightheight())
maxHeight = tmpItem->height();
}
}
if (!bottomPart->isEmpty()){
foreach (BaseDesignIntf* item, bottomPart->childBaseItems()) {
item->setHeight(maxHeight);
}
bottomPart->setHeight(maxHeight);
}
return bottomPart;
}
void HorizontalLayout::restoreChild(BaseDesignIntf* item){
if (m_children.contains(item)) return;
m_isRelocating=true;
foreach (BaseDesignIntf* child, childBaseItems()) {
if (child->pos()==item->pos()){
int index = m_children.indexOf(child)-1;
m_children.insert(index,item);
child->setPos(item->pos().x()+item->width(),0);
break;
}
}
connect(item,SIGNAL(destroyed(QObject*)),this,SLOT(slotOnChildDestroy(QObject*)));
connect(item,SIGNAL(geometryChanged(QObject*,QRectF,QRectF)),this,SLOT(slotOnChildGeometryChanged(QObject*,QRectF,QRectF)));
item->setFixedPos(true);
item->setPosibleResizeDirectionFlags(ResizeRight | ResizeBottom);
item->setParent(this);
item->setParentItem(this);
updateLayoutSize();
m_isRelocating=false;
}
bool HorizontalLayout::isEmpty() const
{
bool isEmpty = true;
bool allItemsIsText = true;
foreach (QGraphicsItem* qgItem, childItems()) {
ContentItemDesignIntf* item = dynamic_cast(qgItem);
if (item && !item->content().isEmpty()) isEmpty = false;
if (!item && dynamic_cast(qgItem))
allItemsIsText = false;
}
return (isEmpty && allItemsIsText);
}
void HorizontalLayout::addChild(BaseDesignIntf *item, bool updateSize)
{
if (m_children.count() > 0)
item->setPos(m_children.last()->pos().x() + m_children.last()->width(), 0);
else
item->setPos(0, 0);
m_children.append(item);
item->setParentItem(this);
item->setParent(this);
item->setFixedPos(true);
item->setPosibleResizeDirectionFlags(ResizeRight | ResizeBottom);
connect(item,SIGNAL(destroyed(QObject*)),this,SLOT(slotOnChildDestroy(QObject*)));
connect(item,SIGNAL(geometryChanged(QObject*,QRectF,QRectF)),this,SLOT(slotOnChildGeometryChanged(QObject*,QRectF,QRectF)));
if (updateSize){
relocateChildren();
updateLayoutSize();
}
}
void HorizontalLayout::collectionLoadFinished(const QString &collectionName)
{
ItemDesignIntf::collectionLoadFinished(collectionName);
if (collectionName.compare("children",Qt::CaseInsensitive)==0){
#ifdef HAVE_QT5
foreach(QObject* obj,children()){
#else
foreach(QObject* obj,QObject::children()){
#endif
BaseDesignIntf* item = dynamic_cast(obj);
if (item) {
addChild(item,false);
}
}
}
}
void HorizontalLayout::objectLoadFinished()
{
m_layoutMarker->setHeight(height());
LayoutDesignIntf::objectLoadFinished();
}
void HorizontalLayout::updateLayoutSize()
{
int w = 0;
qreal h = 0;
foreach(BaseDesignIntf* item, m_children){
if (hheight()) h=item->height();
w+=item->width();
}
if (h>0) setHeight(h);
setWidth(w);
}
void HorizontalLayout::relocateChildren()
{
if (m_children.count()setPos(curX,0);
curX+=item->width();
item->setHeight(height());
}
m_isRelocating = false;
}
void HorizontalLayout::beforeDelete()
{
m_children.clear();
#ifdef HAVE_QT5
foreach (QObject *item, children()) {
#else
foreach (QObject *item, QObject::children()) {
#endif
BaseDesignIntf *bdItem = dynamic_cast(item);
if (bdItem) {
bdItem->setParentItem(parentItem());
bdItem->setParent(parent());
bdItem->setVisible(true);
bdItem->setPos(mapToParent(bdItem->pos()));
bdItem->setFixedPos(false);
bdItem->setPosibleResizeDirectionFlags(AllDirections);
}
}
}
void HorizontalLayout::updateItemSize(RenderPass pass, int maxHeight)
{
m_isRelocating=true;
ItemDesignIntf::updateItemSize(pass,maxHeight);
foreach(QGraphicsItem *child, childItems()){
BaseDesignIntf* item = dynamic_cast(child);
if (item) item->updateItemSize(pass,maxHeight);
}
updateLayoutSize();
relocateChildren();
m_isRelocating=false;
}
bool HorizontalLayout::isNeedUpdateSize(RenderPass pass) const
{
foreach (QGraphicsItem *child, childItems()) {
BaseDesignIntf* item = dynamic_cast(child);
if (item && item->isNeedUpdateSize(pass))
return true;
}
return false;
}
void HorizontalLayout::childAddedEvent(BaseDesignIntf *child)
{
addChild(child,false);
}
void HorizontalLayout::slotOnChildDestroy(QObject* child)
{
m_children.removeAll(static_cast(child));
if (m_children.count()<2){
beforeDelete();
// deleteLater();
} else {
relocateChildren();
updateLayoutSize();
}
}
void HorizontalLayout::slotOnChildGeometryChanged(QObject *, QRectF newGeometry, QRectF)
{
if (!m_isRelocating){
setHeight(newGeometry.height());
relocateChildren();
updateLayoutSize();
}
}
LayoutMarker::LayoutMarker(HorizontalLayout *layout, QGraphicsItem *parent)
:QGraphicsItem(parent), m_rect(0,0,30,30), m_color(Qt::red), m_layout(layout){
setFlag(QGraphicsItem::ItemIsMovable);
}
void LayoutMarker::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->save();
painter->setOpacity(LAYOUT_MARKER_OPACITY);
painter->fillRect(boundingRect(),m_color);
painter->setRenderHint(QPainter::Antialiasing);
qreal size = (boundingRect().width()isSelected()){
painter->setOpacity(1);
QRectF r = QRectF(0,0,size,size);
painter->setBrush(Qt::white);
painter->setPen(Qt::white);
painter->drawEllipse(r.adjusted(5,5,-5,-5));
painter->setBrush(m_color);
painter->drawEllipse(r.adjusted(7,7,-7,-7));
}
painter->restore();
}
void LayoutMarker::setHeight(qreal height)
{
if (m_rect.height()!=height){
prepareGeometryChange();
m_rect.setHeight(height);
}
}
void LayoutMarker::setWidth(qreal width)
{
if (m_rect.width()!=width){
prepareGeometryChange();
m_rect.setWidth(width);
}
}
void LayoutMarker::setColor(QColor color)
{
if (m_color!=color){
m_color = color;
update(boundingRect());
}
}
void LayoutMarker::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button()==Qt::LeftButton) {
if (!(event->modifiers() & Qt::ControlModifier))
m_layout->scene()->clearSelection();
m_layout->setSelected(true);
//m_layout->setChildVisibility(false);
update(0,0,boundingRect().width(),boundingRect().width());
}
}
} // namespace LimeReport