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

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 "widgetfloater.h"
0023 
0024 // Qt
0025 #include <QApplication>
0026 #include <QEvent>
0027 #include <QPointer>
0028 #include <QStyle>
0029 #include <QWidget>
0030 
0031 // Local
0032 
0033 namespace Gwenview
0034 {
0035 struct WidgetFloaterPrivate {
0036     QWidget *mParent = nullptr;
0037     QPointer<QWidget> 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         mInsideUpdateChildGeometry = true;
0053 
0054         int posX, posY;
0055         int childWidth, childHeight;
0056         int parentWidth, parentHeight;
0057 
0058         childWidth = mChild->width();
0059         childHeight = mChild->height();
0060 
0061         parentWidth = mParent->width();
0062         parentHeight = mParent->height();
0063 
0064         if (mAlignment & Qt::AlignLeft) {
0065             posX = mHorizontalMargin;
0066         } else if (mAlignment & Qt::AlignHCenter) {
0067             posX = (parentWidth - childWidth) / 2;
0068         } else if (mAlignment & Qt::AlignJustify) {
0069             posX = mHorizontalMargin;
0070             childWidth = parentWidth - 2 * mHorizontalMargin;
0071             QRect childGeometry = mChild->geometry();
0072             childGeometry.setWidth(childWidth);
0073             mChild->setGeometry(childGeometry);
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         mChild->move(posX, posY);
0087 
0088         mInsideUpdateChildGeometry = false;
0089     }
0090 };
0091 
0092 WidgetFloater::WidgetFloater(QWidget *parent)
0093     : QObject(parent)
0094     , d(new WidgetFloaterPrivate)
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 WidgetFloater::~WidgetFloater()
0108 {
0109     delete d;
0110 }
0111 
0112 void WidgetFloater::setChildWidget(QWidget *child)
0113 {
0114     if (d->mChild) {
0115         d->mChild->removeEventFilter(this);
0116     }
0117     d->mChild = child;
0118     d->mChild->setParent(d->mParent);
0119     d->mChild->installEventFilter(this);
0120     d->updateChildGeometry();
0121     d->mChild->raise();
0122     d->mChild->show();
0123 }
0124 
0125 void WidgetFloater::setAlignment(Qt::Alignment alignment)
0126 {
0127     d->mAlignment = alignment;
0128     d->updateChildGeometry();
0129 }
0130 
0131 bool WidgetFloater::eventFilter(QObject *, QEvent *event)
0132 {
0133     switch (event->type()) {
0134     case QEvent::Resize:
0135     case QEvent::Show:
0136         d->updateChildGeometry();
0137         break;
0138     default:
0139         break;
0140     }
0141     return false;
0142 }
0143 
0144 void WidgetFloater::setHorizontalMargin(int value)
0145 {
0146     d->mHorizontalMargin = value;
0147     d->updateChildGeometry();
0148 }
0149 
0150 int WidgetFloater::horizontalMargin() const
0151 {
0152     return d->mHorizontalMargin;
0153 }
0154 
0155 void WidgetFloater::setVerticalMargin(int value)
0156 {
0157     d->mVerticalMargin = value;
0158     d->updateChildGeometry();
0159 }
0160 
0161 int WidgetFloater::verticalMargin() const
0162 {
0163     return d->mVerticalMargin;
0164 }
0165 
0166 } // namespace
0167 
0168 #include "moc_widgetfloater.cpp"