From 949828080160d360b920e913c3b17eb9c30a23bc Mon Sep 17 00:00:00 2001 From: Asiel Torres Date: Thu, 28 Aug 2025 19:18:18 -0400 Subject: [PATCH] Feat: Add alignment features to position elements to facilitate the design of complex reports - Implement alignToLeftOf function to align an element to the left edge of another. - Implement alignToRightOf function to align an element to the right edge of another. - Implement alignToTopOf function to align an element above another top edge. - Implement alignToBottomOf function to align an element below another bottom edge. --- limereport/images/toBottomOf.png | Bin 0 -> 330 bytes limereport/images/toLeftOf.png | Bin 0 -> 330 bytes limereport/images/toRightOf.png | Bin 0 -> 329 bytes limereport/images/toTopOf.png | Bin 0 -> 329 bytes .../editors/lritemsaligneditorwidget.cpp | 54 ++++++++++ .../items/editors/lritemsaligneditorwidget.h | 9 ++ limereport/lrpagedesignintf.cpp | 93 ++++++++++++++++++ limereport/lrpagedesignintf.h | 4 + limereport/lrreportdesignwidget.cpp | 24 +++++ limereport/lrreportdesignwidget.h | 4 + limereport/report.qrc | 4 + 11 files changed, 192 insertions(+) create mode 100644 limereport/images/toBottomOf.png create mode 100644 limereport/images/toLeftOf.png create mode 100644 limereport/images/toRightOf.png create mode 100644 limereport/images/toTopOf.png diff --git a/limereport/images/toBottomOf.png b/limereport/images/toBottomOf.png new file mode 100644 index 0000000000000000000000000000000000000000..13361e8e8e126c5a7b31197b7f237355b8af88df GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fOS+@4BLl<6 ze(pbstU$g(vPY0F14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>m5< zgt$5~GMsq1-mg;o#EbR&pDsG^Y|(+Ii?=_Vw*BGMZ4ak*oD1wYAGGdX$J%?H>+W_= zznVV%O8U}UHA`<*FTGv6>{jjE>-lr8=Wl&DY0JY&TOUlCaye=8<;2OCla4%JarpU) z?hBz^=Yc5X(%XHP-|lTX14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>m5< zgt#g)Fm#*`vQJd;tJI!;C4Jeg+N}>J9e%#z(%XFxKVRuM7r5o&q$AH)TzSXb?;A|NnoEOpzx*XE2ro`2{mLJiCzwvL>4nJ za0`PlBg3pY5gTe~DWM4fq;G!x literal 0 HcmV?d00001 diff --git a/limereport/images/toRightOf.png b/limereport/images/toRightOf.png new file mode 100644 index 0000000000000000000000000000000000000000..2bcc8f283b59f8e2ac5665e89abfe2a05444e947 GIT binary patch literal 329 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6XVU3I`u#fOS+@4BLl<6 ze(pbstU$g(vPY0F14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>m5< zgt!JWFm#*`vQJd;tJI!;C4Jeg+N}>J9e%#z(%XFxKVRuM7r5o&q$AH)TzSXb?;A|Ns97BBHZ_&R{GF@(X5gcy=QV$l)yTh%9Dc z;1&j9Muu5)B!Gf)o-U3d5|@(`5|SL4O@tEM7*;fh@CfKP14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>m5< zgt!JWFr0X~-mg;o#EbR&pDsG^Y|(+Ii?=_Vw*BGMZ4ak*oD1wYAGGdX$J%?H>+W_= zznVV%O8U}UHA`<*FTGv6>{jjE>-lr8=Wl&DY0JY&TOUlCaye=8<;2OCla4%JarpU) z?hBz^=Yc5X(%XHP-|lTXalignToHCenter(); } +void ItemsAlignmentEditorWidget::slotAlignToTopOf() +{ + if (m_reportEditor) + m_reportEditor->alignToTopOf(); + if (m_page) + m_page->alignToTopOf(); +} + +void ItemsAlignmentEditorWidget::slotAlignToBottomOf() +{ + if (m_reportEditor) + m_reportEditor->alignToBottomOf(); + if (m_page) + m_page->alignToBottomOf(); +} + +void ItemsAlignmentEditorWidget::slotAlignToLeftOf() +{ + if (m_reportEditor) + m_reportEditor->alignToLeftOf(); + if (m_page) + m_page->alignToLeftOf(); +} + +void ItemsAlignmentEditorWidget::slotAlignToRightOf() +{ + if (m_reportEditor) + m_reportEditor->alignToRightOf(); + if (m_page) + m_page->alignToRigthOf(); +} + void ItemsAlignmentEditorWidget::slotSameHeight() { if (m_reportEditor) @@ -188,6 +220,26 @@ void ItemsAlignmentEditorWidget::initEditor() connect(m_alignToHCenter, SIGNAL(triggered()), this, SLOT(slotAlignToHCenter())); addAction(m_alignToHCenter); + m_alignToLeftOf = new QAction(tr("Align to left of"), this); + m_alignToLeftOf->setIcon(QIcon(":/report/images/alignToLeftOf")); + connect(m_alignToLeftOf, SIGNAL(triggered()), this, SLOT(slotAlignToLeftOf())); + addAction(m_alignToLeftOf); + + m_alignToRightOf = new QAction(tr("Align to right of"), this); + m_alignToRightOf->setIcon(QIcon(":/report/images/alignToRightOf")); + connect(m_alignToRightOf, SIGNAL(triggered()), this, SLOT(slotAlignToRightOf())); + addAction(m_alignToRightOf); + + m_alignToTopOf = new QAction(tr("Align to top of"), this); + m_alignToTopOf->setIcon(QIcon(":/report/images/alignToTopOf")); + connect(m_alignToTopOf, SIGNAL(triggered()), this, SLOT(slotAlignToTopOf())); + addAction(m_alignToTopOf); + + m_alignToBottomOf = new QAction(tr("Align to bottom of"), this); + m_alignToBottomOf->setIcon(QIcon(":/report/images/alignToBottomOf")); + connect(m_alignToBottomOf, SIGNAL(triggered()), this, SLOT(slotAlignToBottomOf())); + addAction(m_alignToBottomOf); + m_sameHeight = new QAction(tr("Set same height"), this); m_sameHeight->setIcon(QIcon(":/report/images/sameHeight")); connect(m_sameHeight, SIGNAL(triggered()), this, SLOT(slotSameHeight())); @@ -197,6 +249,8 @@ void ItemsAlignmentEditorWidget::initEditor() m_sameWidth->setIcon(QIcon(":/report/images/sameWidth")); connect(m_sameWidth, SIGNAL(triggered()), this, SLOT(slotSameWidth())); addAction(m_sameWidth); + + } } // namespace LimeReport diff --git a/limereport/items/editors/lritemsaligneditorwidget.h b/limereport/items/editors/lritemsaligneditorwidget.h index cff4a2f2..8f8f181a 100644 --- a/limereport/items/editors/lritemsaligneditorwidget.h +++ b/limereport/items/editors/lritemsaligneditorwidget.h @@ -55,6 +55,10 @@ private slots: void slotAlignToTop(); void slotAlignToBottom(); void slotAlignToHCenter(); + void slotAlignToTopOf(); + void slotAlignToBottomOf(); + void slotAlignToLeftOf(); + void slotAlignToRightOf(); void slotSameHeight(); void slotSameWidth(); @@ -71,8 +75,13 @@ private slots: QAction* m_alignToTop; QAction* m_alignToBottom; QAction* m_alignToHCenter; + QAction* m_alignToTopOf; + QAction* m_alignToBottomOf; + QAction* m_alignToRightOf; + QAction* m_alignToLeftOf; QAction* m_sameHeight; QAction* m_sameWidth; + }; } // namespace LimeReport diff --git a/limereport/lrpagedesignintf.cpp b/limereport/lrpagedesignintf.cpp index b48ebba8..a8318541 100644 --- a/limereport/lrpagedesignintf.cpp +++ b/limereport/lrpagedesignintf.cpp @@ -1649,6 +1649,99 @@ void PageDesignIntf::alignToHCenter() saveCommand(cm, false); } } +void PageDesignIntf::alignToLeftOf() +{ + if ((selectedItems().count() > 0) && m_firstSelectedItem) { + CommandGroup::Ptr cm = CommandGroup::create(); + QPointF previousItemLeftEdge; + foreach (QGraphicsItem* item, selectedItems()) { + BaseDesignIntf* bdItem = dynamic_cast(item); + if (bdItem && !bdItem->isGeometryLocked()) { + QRectF oldGeometry = bdItem->geometry(); + if (previousItemLeftEdge.isNull()) { + bdItem->setPos(m_firstSelectedItem->pos().x() - bdItem->width(), bdItem->pos().y()); + } else { + bdItem->setPos(previousItemLeftEdge.x() - bdItem->width(), bdItem->pos().y()); + } + previousItemLeftEdge = bdItem->pos(); + CommandIf::Ptr command = PropertyChangedCommand::create( + this, bdItem->objectName(), "geometry", oldGeometry, bdItem->geometry()); + cm->addCommand(command, false); + } + } + saveCommand(cm, false); + } +} + +void PageDesignIntf::alignToRigthOf() +{ + if ((selectedItems().count() > 0) && m_firstSelectedItem) { + CommandGroup::Ptr cm = CommandGroup::create(); + QPointF previousItemRightEdge; + foreach (QGraphicsItem* item, selectedItems()) { + BaseDesignIntf* bdItem = dynamic_cast(item); + if (bdItem && !bdItem->isGeometryLocked()) { + QRectF oldGeometry = bdItem->geometry(); + if (previousItemRightEdge.isNull()) { + bdItem->setPos(m_firstSelectedItem->pos().x() + bdItem->width(), bdItem->pos().y()); + } else { + bdItem->setPos(previousItemRightEdge.x() + bdItem->width(), bdItem->pos().y()); + } + previousItemRightEdge = bdItem->pos(); + CommandIf::Ptr command = PropertyChangedCommand::create( + this, bdItem->objectName(), "geometry", oldGeometry, bdItem->geometry()); + cm->addCommand(command, false); + } + } + saveCommand(cm, false); + } +} +void PageDesignIntf::alignToTopOf() +{ + if ((selectedItems().count() > 0) && m_firstSelectedItem) { + CommandGroup::Ptr cm = CommandGroup::create(); + QPointF previousItemTopEdge; + foreach (QGraphicsItem* item, selectedItems()) { + BaseDesignIntf* bdItem = dynamic_cast(item); + if (bdItem && !bdItem->isGeometryLocked()) { + QRectF oldGeometry = bdItem->geometry(); + if (previousItemTopEdge.isNull()) { + bdItem->setPos(bdItem->pos().x(), m_firstSelectedItem->pos().y() + bdItem->height()); + } else { + bdItem->setPos(bdItem->pos().x(), previousItemTopEdge.y() + bdItem->height()); + } + previousItemTopEdge = bdItem->pos(); + CommandIf::Ptr command = PropertyChangedCommand::create( + this, bdItem->objectName(), "geometry", oldGeometry, bdItem->geometry()); + cm->addCommand(command, false); + } + } + saveCommand(cm, false); + } +} +void PageDesignIntf::alignToBottomOf() +{ + if ((selectedItems().count() > 0) && m_firstSelectedItem) { + CommandGroup::Ptr cm = CommandGroup::create(); + QPointF previousItemBottomEdge; + foreach (QGraphicsItem* item, selectedItems()) { + BaseDesignIntf* bdItem = dynamic_cast(item); + if (bdItem && !bdItem->isGeometryLocked()) { + QRectF oldGeometry = bdItem->geometry(); + if (previousItemBottomEdge.isNull()) { + bdItem->setPos(bdItem->pos().x(), m_firstSelectedItem->pos().y() - bdItem->height()); + } else { + bdItem->setPos(bdItem->pos().x(), previousItemBottomEdge.y() - bdItem->height()); + } + previousItemBottomEdge = bdItem->pos(); + CommandIf::Ptr command = PropertyChangedCommand::create( + this, bdItem->objectName(), "geometry", oldGeometry, bdItem->geometry()); + cm->addCommand(command, false); + } + } + saveCommand(cm, false); + } +} void PageDesignIntf::sameWidth() { diff --git a/limereport/lrpagedesignintf.h b/limereport/lrpagedesignintf.h index 35675e6d..78dc9667 100644 --- a/limereport/lrpagedesignintf.h +++ b/limereport/lrpagedesignintf.h @@ -250,6 +250,10 @@ public slots: void alignToTop(); void alignToBottom(); void alignToHCenter(); + void alignToLeftOf(); + void alignToRigthOf(); + void alignToTopOf(); + void alignToBottomOf(); void sameWidth(); void sameHeight(); void addHLayout(); diff --git a/limereport/lrreportdesignwidget.cpp b/limereport/lrreportdesignwidget.cpp index 63a17c68..6346be1a 100644 --- a/limereport/lrreportdesignwidget.cpp +++ b/limereport/lrreportdesignwidget.cpp @@ -654,6 +654,30 @@ void ReportDesignWidget::alignToHCenter() activePage()->alignToHCenter(); } +void ReportDesignWidget::alignToLeftOf() +{ + if (activePage()) + activePage()->alignToLeftOf(); +} + +void ReportDesignWidget::alignToRightOf() +{ + if (activePage()) + activePage()->alignToRigthOf(); +} + +void ReportDesignWidget::alignToTopOf() +{ + if (activePage()) + activePage()->alignToTopOf(); +} + +void ReportDesignWidget::alignToBottomOf() +{ + if (activePage()) + activePage()->alignToBottomOf(); +} + void ReportDesignWidget::sameHeight() { if (activePage()) diff --git a/limereport/lrreportdesignwidget.h b/limereport/lrreportdesignwidget.h index f219df91..094da3f4 100644 --- a/limereport/lrreportdesignwidget.h +++ b/limereport/lrreportdesignwidget.h @@ -194,6 +194,10 @@ public slots: void alignToTop(); void alignToBottom(); void alignToHCenter(); + void alignToLeftOf(); + void alignToRightOf(); + void alignToTopOf(); + void alignToBottomOf(); void sameHeight(); void sameWidth(); void editLayoutMode(bool value); diff --git a/limereport/report.qrc b/limereport/report.qrc index dc597102..a8d6035b 100644 --- a/limereport/report.qrc +++ b/limereport/report.qrc @@ -107,6 +107,10 @@ images/toCenter.png images/toLeft1.png images/toRight.png + images/toLeftOf.png + images/toRightOf.png + images/toTopOf.png + images/toBottomOf.png images/toSameHeight.png images/toSameWidth.png images/toTop.png