File indexing completed on 2024-04-28 04:18:50

0001 // vim: set tabstop=4 shiftwidth=4 expandtab:
0002 /*
0003 Gwenview: an image viewer
0004 Copyright 2008 Aurélien Gâteau <agateau@kde.org>
0005 
0006 This program is free software; you can redistribute it and/or
0007 modify it under the terms of the GNU General Public License
0008 as published by the Free Software Foundation; either version 2
0009 of the License, or (at your option) any later version.
0010 
0011 This program is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU General Public License for more details.
0015 
0016 You should have received a copy of the GNU General Public License
0017 along with this program; if not, write to the Free Software
0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0019 
0020 */
0021 // Self
0022 #include "graphicswidgetfloater.h"
0023 
0024 // Qt
0025 #include <QApplication>
0026 #include <QEvent>
0027 #include <QGraphicsWidget>
0028 #include <QPointer>
0029 #include <QStyle>
0030 
0031 // Local
0032 
0033 namespace Gwenview
0034 {
0035 struct GraphicsWidgetFloaterPrivate {
0036     QGraphicsWidget *mParent = nullptr;
0037     QPointer<QGraphicsWidget> mChild;
0038     Qt::Alignment mAlignment;
0039 
0040     int mHorizontalMargin;
0041     int mVerticalMargin;
0042     bool mInsideUpdateChildGeometry;
0043 
0044     void updateChildGeometry()
0045     {
0046         if (!mChild) {
0047             return;
0048         }
0049         if (mInsideUpdateChildGeometry) {
0050             return;
0051         }
0052 
0053         int posX, posY;
0054         int childWidth, childHeight;
0055         int parentWidth, parentHeight;
0056 
0057         childWidth = mChild->size().width();
0058         childHeight = mChild->size().height();
0059 
0060         parentWidth = mParent->size().width();
0061         parentHeight = mParent->size().height();
0062 
0063         if (parentWidth == 0 || parentHeight == 0) {
0064             return;
0065         }
0066 
0067         if (mAlignment & Qt::AlignLeft) {
0068             posX = mHorizontalMargin;
0069         } else if (mAlignment & Qt::AlignHCenter) {
0070             posX = (parentWidth - childWidth) / 2;
0071         } else if (mAlignment & Qt::AlignJustify) {
0072             posX = mHorizontalMargin;
0073             childWidth = parentWidth - 2 * mHorizontalMargin;
0074         } else {
0075             posX = parentWidth - childWidth - mHorizontalMargin;
0076         }
0077 
0078         if (mAlignment & Qt::AlignTop) {
0079             posY = mVerticalMargin;
0080         } else if (mAlignment & Qt::AlignVCenter) {
0081             posY = (parentHeight - childHeight) / 2;
0082         } else {
0083             posY = parentHeight - childHeight - mVerticalMargin;
0084         }
0085 
0086         mInsideUpdateChildGeometry = true;
0087         mChild->setGeometry(posX, posY, childWidth, childHeight);
0088         mInsideUpdateChildGeometry = false;
0089     }
0090 };
0091 
0092 GraphicsWidgetFloater::GraphicsWidgetFloater(QGraphicsWidget *parent)
0093     : QObject(parent)
0094     , d(new GraphicsWidgetFloaterPrivate)
0095 {
0096     Q_ASSERT(parent);
0097     d->mParent = parent;
0098     d->mParent->installEventFilter(this);
0099     d->mChild = nullptr;
0100     d->mAlignment = Qt::AlignCenter;
0101     // TODO
0102     d->mHorizontalMargin = 0;
0103     d->mVerticalMargin = d->mHorizontalMargin;
0104     d->mInsideUpdateChildGeometry = false;
0105 }
0106 
0107 GraphicsWidgetFloater::~GraphicsWidgetFloater()
0108 {
0109     delete d;
0110 }
0111 
0112 void GraphicsWidgetFloater::setChildWidget(QGraphicsWidget *child)
0113 {
0114     if (d->mChild) {
0115         d->mChild->removeEventFilter(this);
0116         disconnect(d->mChild, nullptr, this, nullptr);
0117     }
0118     d->mChild = child;
0119     d->mChild->setParent(d->mParent);
0120     d->mChild->installEventFilter(this);
0121     connect(d->mChild.data(), &QGraphicsObject::visibleChanged, this, &GraphicsWidgetFloater::slotChildVisibilityChanged);
0122     d->updateChildGeometry();
0123     // d->mChild->raise();
0124     d->mChild->show();
0125 }
0126 
0127 void GraphicsWidgetFloater::setAlignment(Qt::Alignment alignment)
0128 {
0129     d->mAlignment = alignment;
0130     d->updateChildGeometry();
0131 }
0132 
0133 bool GraphicsWidgetFloater::eventFilter(QObject *, QEvent *event)
0134 {
0135     if (event->type() == QEvent::GraphicsSceneResize) {
0136         d->updateChildGeometry();
0137     }
0138     return false;
0139 }
0140 
0141 void GraphicsWidgetFloater::slotChildVisibilityChanged()
0142 {
0143     if (d->mChild->isVisible()) {
0144         d->updateChildGeometry();
0145     }
0146 }
0147 
0148 void GraphicsWidgetFloater::setHorizontalMargin(int value)
0149 {
0150     d->mHorizontalMargin = value;
0151     d->updateChildGeometry();
0152 }
0153 
0154 int GraphicsWidgetFloater::horizontalMargin() const
0155 {
0156     return d->mHorizontalMargin;
0157 }
0158 
0159 void GraphicsWidgetFloater::setVerticalMargin(int value)
0160 {
0161     d->mVerticalMargin = value;
0162     d->updateChildGeometry();
0163 }
0164 
0165 int GraphicsWidgetFloater::verticalMargin() const
0166 {
0167     return d->mVerticalMargin;
0168 }
0169 
0170 } // namespace
0171 
0172 #include "moc_graphicswidgetfloater.cpp"