/*************************************************************************** * This file is part of the Lime Report project * * Copyright (C) 2021 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 "lrbanddesignintf.h" #include "lrglobal.h" #include "lritemdesignintf.h" #include #include #include #include namespace LimeReport { BandMarker::BandMarker(BandDesignIntf* band, QGraphicsItem* parent): QGraphicsItem(parent), m_rect(0, 0, 30, 30), m_band(band) { setAcceptHoverEvents(true); } QRectF BandMarker::boundingRect() const { return m_rect; } void BandMarker::paint(QPainter* painter, const QStyleOptionGraphicsItem* /**option*/, QWidget* /*widget*/) { painter->save(); painter->setOpacity(Const::BAND_MARKER_OPACITY); painter->fillRect(boundingRect(), m_color); painter->setOpacity(1); painter->setPen(QPen(QBrush(Qt::lightGray), 2)); painter->fillRect(QRectF(boundingRect().bottomLeft().x(), boundingRect().bottomLeft().y() - 4, boundingRect().width(), 4), Qt::lightGray); painter->setRenderHint(QPainter::Antialiasing); qreal size = (boundingRect().width() < boundingRect().height()) ? boundingRect().width() : boundingRect().height(); QRectF r = QRectF(0, 0, size, size); painter->setBrush(Qt::white); painter->setPen(Qt::white); painter->drawEllipse(r.adjusted(5, 5, -5, -5)); if (m_band->isSelected()) { painter->setBrush(LimeReport::Const::SELECTION_COLOR); painter->drawEllipse(r.adjusted(7, 7, -7, -7)); } painter->restore(); } void BandMarker::setHeight(qreal height) { if (m_rect.height() != height) { prepareGeometryChange(); m_rect.setHeight(height); } } void BandMarker::setWidth(qreal width) { if (m_rect.width() != width) { prepareGeometryChange(); m_rect.setWidth(width); } } void BandMarker::setColor(QColor color) { if (m_color != color) { m_color = color; update(boundingRect()); } } void BandMarker::mousePressEvent(QGraphicsSceneMouseEvent* event) { if (event->button() == Qt::LeftButton) { if (!(event->modifiers() & Qt::ControlModifier)) m_band->scene()->clearSelection(); m_band->setSelected(true); m_oldBandPos = m_band->pos(); update(0, 0, boundingRect().width(), boundingRect().width()); } } void BandMarker::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) { m_band->contextMenuEvent(event); } void BandMarker::hoverMoveEvent(QGraphicsSceneHoverEvent* event) { if (QRectF(0, height() - 10, width(), 10).contains(event->pos())) { setCursor(Qt::SizeVerCursor); } else { unsetCursor(); } } void BandMarker::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { qreal delta = event->pos().y() - event->lastPos().y(); if (hasCursor()) { m_band->setHeight(m_band->height() + delta); } else { if (!m_band->isFixedPos()) m_band->setItemPos(QPointF(m_band->pos().x(), m_band->pos().y() + delta)); } } void BandMarker::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { Q_UNUSED(event) m_band->posChanged(m_band, m_band->pos(), m_oldBandPos); } BandDesignIntf::BandDesignIntf(BandsType bandType, const QString& xmlTypeName, QObject* owner, QGraphicsItem* parent): ItemsContainerDesignInft(xmlTypeName, owner, parent), m_bandType(bandType), m_bandIndex(static_cast(bandType)), m_dataSourceName(""), m_autoHeight(true), m_keepBottomSpace(false), m_keepTopSpace(true), m_parentBand(0), m_parentBandName(""), m_bandMarker(0), m_tryToKeepTogether(false), m_splitable(false), m_keepFooterTogether(false), m_maxScalePercent(0), m_sliceLastRow(false), m_printIfEmpty(false), m_columnsCount(1), m_columnIndex(0), m_columnsFillDirection(Horizontal), m_reprintOnEachPage(false), m_startNewPage(false), m_startFromNewPage(false), m_printAlways(false), m_repeatOnEachRow(false), m_useAlternateBackgroundColor(false), m_bottomSpace(0), m_shiftItems(0) { setPossibleResizeDirectionFlags(ResizeBottom); setPossibleMoveFlags(TopBotom); if (parent) { BaseDesignIntf* parentItem = dynamic_cast(parent); if (parentItem) setWidth(parentItem->width()); } setBackgroundMode(BaseDesignIntf::TransparentMode); setFillTransparentInDesignMode(false); setHeight(100); setFixedPos(true); setFlag(QGraphicsItem::ItemClipsChildrenToShape); m_bandMarker = new BandMarker(this); m_bandMarker->setColor(Qt::magenta); m_bandMarker->setHeight(height()); m_bandMarker->setPos(pos().x() - m_bandMarker->width() - (itemMode() == ItemModes::PrintMode ? boundingRect().width() : 0), pos().y()); if (scene()) scene()->addItem(m_bandMarker); m_bandNameLabel = new BandNameLabel(this); m_bandNameLabel->setVisible(false); if (scene()) scene()->addItem(m_bandNameLabel); m_alternateBackgroundColor = backgroundColor(); connect(this, SIGNAL(propertyObjectNameChanged(QString, QString)), this, SLOT(slotPropertyObjectNameChanged(const QString&, const QString&))); } BandDesignIntf::~BandDesignIntf() { delete m_bandMarker; delete m_bandNameLabel; } int extractItemIndex(const BaseDesignIntf* item) { QString objectName = extractClassName(item->metaObject()->className()); QString value = item->objectName().right(item->objectName().size() - objectName.size()); return value.toInt(); } QString BandDesignIntf::translateBandName(const BaseDesignIntf* item) const { QString defaultBandName = extractClassName(item->metaObject()->className()).toLatin1() + QString::number(extractItemIndex(item)); if (item->objectName().compare(defaultBandName) == 0) { return tr(extractClassName(item->metaObject()->className()).toLatin1()) + QString::number(extractItemIndex(item)); } else { return item->objectName(); } } void BandDesignIntf::setBackgroundModeProperty(BaseDesignIntf::BGMode value) { if (value != backgroundMode()) { BaseDesignIntf::BGMode oldValue = backgroundMode(); setBackgroundMode(value); notify("backgroundMode", oldValue, value); } } void BandDesignIntf::setBackgroundOpacity(int value) { if (opacity() != value) { int oldValue = opacity(); setOpacity(value); notify("backgroundOpacity", oldValue, value); } } bool BandDesignIntf::isNeedUpdateSize(RenderPass pass) const { foreach (BaseDesignIntf* item, childBaseItems()) { if (item->isNeedUpdateSize(pass)) return true; } return false; } void BandDesignIntf::copyBandAttributes(BandDesignIntf* source) { this->copyBookmarks(source); this->setBackgroundColor(source->backgroundColor()); } void BandDesignIntf::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { prepareRect(painter, option, widget); if (itemMode() & DesignMode) { painter->save(); QString bandText = bandTitle(); QFont font("Arial", 7 * Const::fontFACTOR, -1, true); QFontMetrics fontMetrics(font); QVector bandNameRects; bandNameRects.push_back(QRectF(8, 8, fontMetrics.boundingRect(" " + bandText + " ").width(), fontMetrics.height())); // bandNameRects.push_back(QRectF(width()-fontMetrics.width(" "+bandText+" // "),2,fontMetrics.width(" "+bandText+" "),fontMetrics.height())); // bandNameRects.push_back(QRectF(2,height()-fontMetrics.height(),fontMetrics.width(" // "+bandText+" "),fontMetrics.height())); // bandNameRects.push_back(QRectF(width()-fontMetrics.width(" "+bandText+" // "),height()-fontMetrics.height(),fontMetrics.width(" "+bandText+" // "),fontMetrics.height())); if (bandNameRects[0].intersects(bandNameRects[2])) // bandNameRects.remove(2,2); if (isSelected()) ppainter->setPen(QColor(167,244,167)); // else ppainter->setPen(QColor(220,220,220)); painter->setFont(font); for (int i = 0; i < bandNameRects.count(); i++) { QRectF labelRect = bandNameRects[i].adjusted(-2, -2, 2, 2); if ((labelRect.height()) < height() && (childBaseItems().isEmpty()) && !isSelected()) { painter->setRenderHint(QPainter::Antialiasing); painter->setBrush(bandColor()); painter->setOpacity(Const::BAND_NAME_AREA_OPACITY); painter->drawRoundedRect(labelRect, 8, 8); painter->setOpacity(Const::BAND_NAME_TEXT_OPACITY); painter->setPen(Qt::black); painter->drawText(bandNameRects[i], Qt::AlignHCenter, bandText); } } painter->restore(); } BaseDesignIntf::paint(painter, option, widget); } QRectF BandDesignIntf::boundingRect() const { return ItemsContainerDesignInft::boundingRect().adjusted(0, -4, 0, 4); } void BandDesignIntf::translateBandsName() { tr("DataBand"); tr("DataHeaderBand"); tr("DataFooterBand"); tr("ReportHeader"); tr("ReportFooter"); tr("PageHeader"); tr("PageFooter"); tr("SubDetailBand"); tr("SubDetailHeaderBand"); tr("SubDetailFooterBand"); tr("GroupBandHeader"); tr("GroupBandFooter"); tr("TearOffBand"); } BandDesignIntf::BandsType BandDesignIntf::bandType() const { return m_bandType; } QString BandDesignIntf::bandTitle() const { QString result = translateBandName(this); if (parentBand()) result += tr(" connected to ") + translateBandName(parentBand()); return result; } QIcon BandDesignIntf::bandIcon() const { return QIcon(); } int BandDesignIntf::bandIndex() const { return m_bandIndex; } void BandDesignIntf::setBandIndex(int value) { m_bandIndex = value; } void BandDesignIntf::changeBandIndex(int value, bool firstTime) { int indexOffset; if (firstTime && bandHeader()) value += 1; indexOffset = value - m_bandIndex; foreach (BandDesignIntf* band, childBands()) { int newIndex = band->bandIndex() + indexOffset; band->changeBandIndex(newIndex); } setBandIndex(value); } bool BandDesignIntf::isUnique() const { return true; } void BandDesignIntf::setItemMode(BaseDesignIntf::ItemMode mode) { ItemsContainerDesignInft::setItemMode(mode); updateBandMarkerGeometry(); } QString BandDesignIntf::datasourceName() { return m_dataSourceName; } void BandDesignIntf::setDataSourceName(const QString& datasource) { m_dataSourceName = datasource; } void BandDesignIntf::setKeepBottomSpace(bool value) { if (m_keepBottomSpace != value) { m_keepBottomSpace = value; if (!isLoading()) notify("keepBottomSpace", !value, value); } } void BandDesignIntf::addChildBand(BandDesignIntf* band) { m_childBands.append(band); connect(band, SIGNAL(destroyed(QObject*)), this, SLOT(childBandDeleted(QObject*))); } void BandDesignIntf::removeChildBand(BandDesignIntf* band) { m_childBands.removeAt(m_childBands.indexOf(band)); } void BandDesignIntf::setParentBand(BandDesignIntf* band) { m_parentBand = band; if (band) { if (parentBandName().compare(band->objectName(), Qt::CaseInsensitive) != 0) setParentBandName(band->objectName()); band->addChildBand(this); } } void BandDesignIntf::setParentBandName(const QString& parentBandName) { m_parentBandName = parentBandName; if (itemMode() & DesignMode && !m_parentBandName.isEmpty()) { if ((parentBand() == 0) || (parentBand()->objectName() != parentBandName)) setParentBand(findParentBand()); } } QString BandDesignIntf::parentBandName() { if (!m_parentBand) return m_parentBandName; else return m_parentBand->objectName(); } bool BandDesignIntf::isConnectedToBand(BandDesignIntf::BandsType bandType) const { foreach (BandDesignIntf* band, childBands()) if (band->bandType() == bandType) return true; return false; } int BandDesignIntf::maxChildIndex(BandDesignIntf::BandsType bandType) const { int curIndex = bandIndex(); foreach (BandDesignIntf* childBand, childBands()) { if ((childBand->bandIndex() > bandIndex()) && (childBand->bandType() < bandType)) { curIndex = std::max(curIndex, childBand->maxChildIndex()); } } return curIndex; } int BandDesignIntf::maxChildIndex(QSet ignoredBands) const { int curIndex = bandIndex(); foreach (BandDesignIntf* childBand, childBands()) { if (!ignoredBands.contains(childBand->bandType())) { curIndex = std::max(curIndex, childBand->maxChildIndex(ignoredBands)); } } return curIndex; } int BandDesignIntf::rootIndex(BandDesignIntf* parentBand) { return rootBand(parentBand)->bandIndex(); } BandDesignIntf* BandDesignIntf::rootBand(BandDesignIntf* parentBand) { BandDesignIntf* currentBand = this; while (currentBand->parentBand() && currentBand->parentBand() != parentBand) currentBand = currentBand->parentBand(); return currentBand; } int BandDesignIntf::minChildIndex(BandDesignIntf::BandsType bandType) { int curIndex = bandIndex(); foreach (BandDesignIntf* childBand, childBands()) { if (curIndex > childBand->bandIndex() && (childBand->bandType() > bandType)) { curIndex = childBand->bandIndex(); } } return curIndex; } int BandDesignIntf::minChildIndex(QSet ignoredBands) { int curIndex = bandIndex(); foreach (BandDesignIntf* childBand, childBands()) { if (!ignoredBands.contains(childBand->bandType()) && childBand->bandIndex() < bandIndex()) { curIndex = std::min(curIndex, childBand->minChildIndex(ignoredBands)); } } return curIndex; } QList BandDesignIntf::childrenByType(BandDesignIntf::BandsType type) { QList resList; foreach (BandDesignIntf* item, childBands()) { if (item->bandType() == type) resList << item; } std::sort(resList.begin(), resList.end(), bandIndexLessThen); return resList; } bool BandDesignIntf::canBeSplitted(int height) const { if (isSplittable()) { foreach (QGraphicsItem* qgItem, childItems()) { BaseDesignIntf* item = dynamic_cast(qgItem); if (item) if ((item->minHeight() > height) && (item->minHeight() > (this->height() - height))) return false; } } return isSplittable(); } bool BandDesignIntf::isEmpty() const { if (!isVisible()) return true; foreach (QGraphicsItem* qgItem, childItems()) { BaseDesignIntf* item = dynamic_cast(qgItem); if ((item) && (!item->isEmpty())) return false; } return true; } bool BandDesignIntf::isNeedRender() const { return true; } void BandDesignIntf::setTryToKeepTogether(bool value) { if (m_tryToKeepTogether != value) { m_tryToKeepTogether = value; if (!isLoading()) notify("keepSubdetailTogether", !value, value); } } bool BandDesignIntf::tryToKeepTogether() { return m_tryToKeepTogether; } void BandDesignIntf::checkEmptyTable() { bool isEmpty = true; bool allItemsIsText = true; foreach (QGraphicsItem* qgItem, childItems()) { BaseDesignIntf* item = dynamic_cast(qgItem); if (item && !item->isEmpty()) isEmpty = false; if (!item) allItemsIsText = false; } if (isEmpty && allItemsIsText) { foreach (QGraphicsItem* qgItem, childItems()) { ContentItemDesignIntf* item = dynamic_cast(qgItem); item->setHeight(0); } } } void BandDesignIntf::setColumnsCount(int value) { if (m_columnsCount != value && value > 0) { qreal oldValue = m_columnsCount; qreal fullWidth = m_columnsCount * width(); m_columnsCount = value; if (!isLoading()) { setWidth(fullWidth / m_columnsCount); notify("columnsCount", oldValue, value); } } } void BandDesignIntf::setColumnsFillDirection(BandDesignIntf::BandColumnsLayoutType value) { if (m_columnsFillDirection != value) { qreal oldValue = m_columnsFillDirection; m_columnsFillDirection = value; if (!isLoading()) notify("columnsFillDirection", oldValue, value); } } void BandDesignIntf::moveItemsDown(qreal startPos, qreal offset) { foreach (QGraphicsItem* item, childItems()) { if (item->pos().y() >= startPos) item->setPos(item->x(), item->y() + offset); } } void BandDesignIntf::preparePopUpMenu(QMenu& menu) { QList disabledActions; disabledActions << tr("Bring to top") << tr("Send to back") << tr("Cut") << tr("Copy"); foreach (QAction* action, menu.actions()) { action->setEnabled(!disabledActions.contains(action->text())); } menu.addSeparator(); QAction* currAction = menu.addAction(tr("Auto height")); currAction->setCheckable(true); currAction->setChecked(autoHeight()); currAction = menu.addAction(tr("Splittable")); currAction->setEnabled(metaObject()->indexOfProperty("splittable") != -1); currAction->setCheckable(true); currAction->setChecked(isSplittable()); currAction = menu.addAction(tr("Keep top space")); currAction->setCheckable(true); currAction->setChecked(keepTopSpace()); currAction = menu.addAction(tr("Keep bottom space")); currAction->setCheckable(true); currAction->setChecked(keepBottomSpace()); currAction = menu.addAction(tr("Print if empty")); currAction->setCheckable(true); currAction->setChecked(printIfEmpty()); } void BandDesignIntf::processPopUpAction(QAction* action) { if (action->text().compare(tr("Auto height")) == 0) { setProperty("autoHeight", action->isChecked()); } if (action->text().compare(tr("Splittable")) == 0) { setProperty("splittable", action->isChecked()); } if (action->text().compare(tr("Keep top space")) == 0) { setProperty("keepTopSpace", action->isChecked()); } if (action->text().compare(tr("Keep bottom space")) == 0) { setProperty("keepBottomSpace", action->isChecked()); } if (action->text().compare(tr("Keep top space")) == 0) { setProperty("keepTopSpace", action->isChecked()); } if (action->text().compare(tr("Print if empty")) == 0) { setProperty("printIfEmpty", action->isChecked()); } ItemsContainerDesignInft::processPopUpAction(action); } BaseDesignIntf* BandDesignIntf::cloneUpperPart(int height, QObject* owner, QGraphicsItem* parent) { int maxBottom = 0; BandDesignIntf* upperPart = dynamic_cast(createSameTypeItem(owner, parent)); BaseDesignIntf* upperItem = 0; upperPart->initFromItem(this); foreach (QGraphicsItem* qgItem, childItems()) { BaseDesignIntf* item = dynamic_cast(qgItem); if (item) { if (item->geometry().bottom() <= height) { upperItem = item->cloneItem(item->itemMode(), upperPart, upperPart); if (maxBottom < upperItem->geometry().bottom()) maxBottom = upperItem->geometry().bottom(); } else if ((item->geometry().top() < height) && (item->geometry().bottom() > height)) { int sliceHeight = height - item->geometry().top(); if (!item->isSplittable()) { if (sliceHeight > (this->height() - sliceHeight)) { upperItem = item->cloneItem(item->itemMode(), upperPart, upperPart); upperItem->setHeight(height); } else { item->cloneEmpty(sliceHeight, upperPart, upperPart); // for table // qgItem->setPos(item->pos().x(),item->pos().y()+((height+1)-item->geometry().top())); moveItemsDown(item->pos().y(), (height + 1) - item->geometry().top()); } } else if (item->canBeSplitted(sliceHeight)) { upperItem = item->cloneUpperPart(sliceHeight, upperPart, upperPart); if (maxBottom < upperItem->geometry().bottom()) maxBottom = upperItem->geometry().bottom(); m_slicedItems.insert(upperItem->objectName(), upperItem); } else { item->cloneEmpty(sliceHeight, upperPart, upperPart); // for table moveItemsDown(item->pos().y(), (height + 1) - item->geometry().top()); // qgItem->setPos(item->pos().x(),item->pos().y()+((height+1)-item->geometry().top())); } } } } upperPart->setHeight(height); return upperPart; } bool itemLessThen(QGraphicsItem* i1, QGraphicsItem* i2) { return i1->pos().y() < i2->pos().y(); } BaseDesignIntf* BandDesignIntf::cloneBottomPart(int height, QObject* owner, QGraphicsItem* parent) { BandDesignIntf* bottomPart = dynamic_cast(createSameTypeItem(owner, parent)); bottomPart->initFromItem(this); QList bandItems; bandItems = childItems(); std::sort(bandItems.begin(), bandItems.end(), itemLessThen); foreach (QGraphicsItem* qgItem, bandItems) { BaseDesignIntf* item = dynamic_cast(qgItem); if (item) { if (item->geometry().top() > height) { BaseDesignIntf* tmpItem = item->cloneItem(item->itemMode(), bottomPart, bottomPart); tmpItem->setPos(tmpItem->pos().x(), (tmpItem->pos().y() - height) + borderLineSize()); } else if ((item->geometry().top() <= height) && (item->geometry().bottom() > height)) { int sliceHeight = height - item->geometry().top(); if (item->isSplittable() && item->canBeSplitted(sliceHeight)) { BaseDesignIntf* tmpItem = item->cloneBottomPart(sliceHeight, bottomPart, bottomPart); tmpItem->setPos(tmpItem->pos().x(), borderLineSize()); BaseDesignIntf* slicedItem = m_slicedItems.value(tmpItem->objectName()); if (slicedItem) { qreal sizeOffset = (slicedItem->height() + tmpItem->height()) - item->height(); qreal bottomOffset = (height - slicedItem->pos().y()) - m_slicedItems.value(tmpItem->objectName())->height(); moveItemsDown(item->pos().y() + item->height(), sizeOffset + bottomOffset); } } else { BaseDesignIntf* tmpItem = item->cloneItem(item->itemMode(), bottomPart, bottomPart); tmpItem->setPos(tmpItem->pos().x(), borderLineSize()); } } } } return bottomPart; } void BandDesignIntf::parentObjectLoadFinished() { if (!parentBandName().isEmpty()) setParentBand(findParentBand()); } void BandDesignIntf::objectLoadFinished() { m_bandMarker->setHeight(height()); BaseDesignIntf::objectLoadFinished(); } void BandDesignIntf::emitBandRendered(BandDesignIntf* band) { emit bandRendered(band); } void BandDesignIntf::emitBandReRendered(BandDesignIntf* oldBand, BandDesignIntf* newBand) { emit bandReRendered(oldBand, newBand); } void BandDesignIntf::setSplittable(bool value) { if (m_splitable != value) { bool oldValue = m_splitable; m_splitable = value; if (!isLoading()) notify("splittable", oldValue, value); } } bool bandIndexLessThen(const BandDesignIntf* b1, const BandDesignIntf* b2) { return b1->bandIndex() < b2->bandIndex(); } void BandDesignIntf::trimToMaxHeight(int maxHeight) { foreach (BaseDesignIntf* item, childBaseItems()) { if (item->height() > maxHeight) item->setHeight(maxHeight); } } void BandDesignIntf::setBandTypeText(const QString& value) { m_bandTypeText = value; m_bandNameLabel->updateLabel(bandTitle()); } QSet BandDesignIntf::groupBands() { QSet result; result << GroupHeader << GroupFooter; return result; } QSet BandDesignIntf::subdetailBands() { QSet result; result << SubDetailBand << SubDetailHeader << SubDetailFooter; return result; } BandDesignIntf* BandDesignIntf::findParentBand() { if (parent() && (!dynamic_cast(parent())->isLoading())) { foreach (QObject* item, parent()->children()) { BandDesignIntf* band = dynamic_cast(item); if (band && (band->objectName().compare(parentBandName(), Qt::CaseInsensitive) == 0)) return band; } } return 0; } void BandDesignIntf::updateBandMarkerGeometry() { if (parentItem() && m_bandMarker) { m_bandMarker->setPos( pos().x() - m_bandMarker->width() - (itemMode() == ItemModes::PrintMode ? boundingRect().width() : 0), pos().y()); m_bandMarker->setHeight(rect().height()); } } void BandDesignIntf::geometryChangedEvent(QRectF, QRectF) { if (((itemMode() & DesignMode) || (itemMode() & EditMode)) && parentItem()) { updateBandMarkerGeometry(); } foreach (BaseDesignIntf* item, childBaseItems()) { if (item->itemAlign() != DesignedItemAlign) { item->updateItemAlign(); } } } QVariant BandDesignIntf::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value) { if ((change == ItemPositionChange) && ((itemMode() & DesignMode) || (itemMode() & EditMode))) { if (m_bandMarker) { m_bandMarker->setPos( (value.toPointF().x() - m_bandMarker->boundingRect().width() - (itemMode() == ItemModes::PrintMode ? boundingRect().width() : 0)), value.toPointF().y()); } } if (change == ItemSelectedChange) { if (m_bandMarker) { m_bandMarker->update(0, 0, m_bandMarker->boundingRect().width(), m_bandMarker->boundingRect().width()); m_bandNameLabel->updateLabel(bandTitle()); m_bandNameLabel->setVisible(value.toBool()); } } if (change == ItemChildAddedChange || change == ItemChildRemovedChange) { update(rect()); } return BaseDesignIntf::itemChange(change, value); } void BandDesignIntf::initMode(ItemMode mode) { BaseDesignIntf::initMode(mode); if ((mode == PreviewMode) || (mode == PrintMode)) { m_bandMarker->setVisible(false); } else { if (!m_bandMarker->scene() && this->scene()) { this->scene()->addItem(m_bandMarker); m_bandMarker->setParentItem(this->parentItem()); m_bandMarker->setHeight(this->height()); } m_bandMarker->setVisible(true); } } QColor BandDesignIntf::bandColor() const { return Qt::darkBlue; } void BandDesignIntf::setMarkerColor(QColor color) { if (m_bandMarker) m_bandMarker->setColor(color); } void BandDesignIntf::childBandDeleted(QObject* band) { m_childBands.removeAt(m_childBands.indexOf(reinterpret_cast(band))); } bool BandDesignIntf::useAlternateBackgroundColor() const { return m_useAlternateBackgroundColor; } void BandDesignIntf::setUseAlternateBackgroundColor(bool useAlternateBackgroundColor) { if (m_useAlternateBackgroundColor != useAlternateBackgroundColor) { QColor oldValue = m_useAlternateBackgroundColor; m_useAlternateBackgroundColor = useAlternateBackgroundColor; if (!isLoading()) notify("useAlternateBackgroundColor", oldValue, useAlternateBackgroundColor); } } QColor BandDesignIntf::alternateBackgroundColor() const { if (metaObject()->indexOfProperty("alternateBackgroundColor") != -1) return m_alternateBackgroundColor; else return backgroundColor(); } void BandDesignIntf::setAlternateBackgroundColor(const QColor& alternateBackgroundColor) { if (m_alternateBackgroundColor != alternateBackgroundColor) { QColor oldValue = m_alternateBackgroundColor; m_alternateBackgroundColor = alternateBackgroundColor; if (!isLoading()) notify("alternateBackgroundColor", oldValue, alternateBackgroundColor); } } qreal BandDesignIntf::bottomSpace() { return m_bottomSpace; } void BandDesignIntf::slotPropertyObjectNameChanged(const QString&, const QString& newName) { update(); if (m_bandNameLabel) m_bandNameLabel->updateLabel(newName); } int BandDesignIntf::shiftItems() const { return m_shiftItems; } void BandDesignIntf::setShiftItems(int shiftItems) { m_shiftItems = shiftItems; } bool BandDesignIntf::keepTopSpace() const { return m_keepTopSpace; } void BandDesignIntf::setKeepTopSpace(bool value) { if (m_keepTopSpace != value) { m_keepTopSpace = value; if (!isLoading()) notify("keepTopSpace", !value, value); } } void BandDesignIntf::setBottomSpace(qreal bottomSpace) { m_bottomSpace = bottomSpace; } bool BandDesignIntf::repeatOnEachRow() const { return m_repeatOnEachRow; } void BandDesignIntf::setRepeatOnEachRow(bool repeatOnEachRow) { if (m_repeatOnEachRow != repeatOnEachRow) { m_repeatOnEachRow = repeatOnEachRow; if (!isLoading()) notify("repeatOnEachRow", !m_repeatOnEachRow, m_repeatOnEachRow); } } bool BandDesignIntf::printAlways() const { return m_printAlways; } void BandDesignIntf::setPrintAlways(bool printAlways) { if (m_printAlways != printAlways) { m_printAlways = printAlways; if (!isLoading()) notify("printAlways", !m_printAlways, m_printAlways); } } bool BandDesignIntf::startFromNewPage() const { return m_startFromNewPage; } void BandDesignIntf::setStartFromNewPage(bool startWithNewPage) { if (m_startFromNewPage != startWithNewPage) { m_startFromNewPage = startWithNewPage; if (!isLoading()) notify("startFromNewPage", !startWithNewPage, startWithNewPage); } } bool BandDesignIntf::startNewPage() const { return m_startNewPage; } void BandDesignIntf::setStartNewPage(bool startNewPage) { if (m_startNewPage != startNewPage) { m_startNewPage = startNewPage; if (!isLoading()) notify("startNewPage", !startNewPage, startNewPage); } } void BandDesignIntf::setAutoHeight(bool value) { if (m_autoHeight != value) { m_autoHeight = value; if (!isLoading()) notify("autoHeight", !value, value); } } bool BandDesignIntf::reprintOnEachPage() const { return m_reprintOnEachPage; } void BandDesignIntf::setReprintOnEachPage(bool reprintOnEachPage) { if (m_reprintOnEachPage != reprintOnEachPage) { m_reprintOnEachPage = reprintOnEachPage; if (!isLoading()) notify("reprintOnEachPage", !m_reprintOnEachPage, m_reprintOnEachPage); } } int BandDesignIntf::columnIndex() const { return m_columnIndex; } void BandDesignIntf::setColumnIndex(int columnIndex) { m_columnIndex = columnIndex; } bool BandDesignIntf::printIfEmpty() const { return m_printIfEmpty; } void BandDesignIntf::setPrintIfEmpty(bool printIfEmpty) { if (m_printIfEmpty != printIfEmpty) { m_printIfEmpty = printIfEmpty; if (!isLoading()) notify("printIfEmpty", !m_printIfEmpty, m_printIfEmpty); } } BandDesignIntf* BandDesignIntf::bandHeader() { foreach (BandDesignIntf* band, childBands()) { if (band->isHeader() && !band->isGroupHeader()) { if (band->columnsCount() > 1) band->setColumnsFillDirection(this->columnsFillDirection()); return band; } } return 0; } BandDesignIntf* BandDesignIntf::bandFooter() { foreach (BandDesignIntf* band, childBands()) { if (band->isFooter()) return band; } return 0; } bool BandDesignIntf::sliceLastRow() const { return m_sliceLastRow; } void BandDesignIntf::setSliceLastRow(bool sliceLastRow) { if (m_sliceLastRow != sliceLastRow) { m_sliceLastRow = sliceLastRow; if (!isLoading()) notify("sliceLastRow", !sliceLastRow, sliceLastRow); } } int BandDesignIntf::maxScalePercent() const { return m_maxScalePercent; } void BandDesignIntf::setMaxScalePercent(int maxScalePercent) { m_maxScalePercent = maxScalePercent; } bool BandDesignIntf::keepFooterTogether() const { return m_keepFooterTogether; } void BandDesignIntf::setKeepFooterTogether(bool value) { if (m_keepFooterTogether != value) { bool oldValue = m_keepFooterTogether; m_keepFooterTogether = value; if (!isLoading()) notify("keepFooterTogether", oldValue, value); } } void BandDesignIntf::updateItemSize(DataSourceManager* dataManager, RenderPass pass, int maxHeight) { qreal spaceBorder = 0; if (keepBottomSpace()) spaceBorder = bottomSpace(); spaceBorder = spaceBorder > 0 ? spaceBorder : 0; if (borderLines() != 0) { spaceBorder += borderLineSize() + 2; } restoreLinks(); snapshotItemsLayout(); arrangeSubItems(pass, dataManager); if (autoHeight()) { if (!keepTopSpace()) { qreal minTop = findMinTop() + m_shiftItems; foreach (BaseDesignIntf* item, childBaseItems()) { item->setY(item->y() - minTop); } } setHeight(findMaxBottom() + spaceBorder); } if ((maxHeight > 0) && (height() > maxHeight)) { trimToMaxHeight(maxHeight); setHeight(maxHeight); } BaseDesignIntf::updateItemSize(dataManager, pass, maxHeight); } void BandDesignIntf::updateBandNameLabel() { if (m_bandNameLabel) m_bandNameLabel->updateLabel(bandTitle()); } void BandDesignIntf::initFromItem(BaseDesignIntf* source) { ItemsContainerDesignInft::initFromItem(source); BandDesignIntf* source_band = dynamic_cast(source); if (source_band) { this->setBottomSpace(source_band->bottomSpace()); } } QColor BandDesignIntf::selectionColor() const { return Qt::yellow; } DataBandDesignIntf::DataBandDesignIntf(BandDesignIntf::BandsType bandType, QString xmlTypeName, QObject* owner, QGraphicsItem* parent): BandDesignIntf(bandType, xmlTypeName, owner, parent) { } BandNameLabel::BandNameLabel(BandDesignIntf* band, QGraphicsItem* parent): QGraphicsItem(parent), m_rect(5, 5, 30, 30), m_band(band) { setAcceptHoverEvents(true); } void BandNameLabel::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { painter->save(); painter->setRenderHint(QPainter::Antialiasing); painter->setFont(QFont("Arial", 7 * Const::fontFACTOR, -1, true)); painter->setOpacity(1); QPen pen(Const::BAND_NAME_BORDER_COLOR); // pen.setWidth(2); painter->setBrush(Qt::yellow); painter->setPen(pen); painter->drawRoundedRect(m_rect, 8, 8); painter->setOpacity(0.8); painter->setPen(Qt::black); painter->drawText(m_rect, Qt::AlignCenter, m_band->bandTitle()); painter->restore(); Q_UNUSED(option) Q_UNUSED(widget) } QRectF BandNameLabel::boundingRect() const { return m_rect; } void BandNameLabel::updateLabel(const QString& bandName) { QFont font("Arial", 7 * Const::fontFACTOR, -1, true); QFontMetrics fontMetrics(font); prepareGeometryChange(); m_rect = QRectF(m_band->pos().x() + 10, m_band->pos().y() - (fontMetrics.height() + 10), fontMetrics.boundingRect(bandName).width() + 20, fontMetrics.height() + 10); update(); } void BandNameLabel::hoverEnterEvent(QGraphicsSceneHoverEvent* event) { setVisible(false); Q_UNUSED(event) } } // namespace LimeReport