File indexing completed on 2024-05-12 05:08:00

0001 /*
0002     SPDX-FileCopyrightText: 2021      Thomas Baumgart <tbaumgart@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "popuppositioner.h"
0007 
0008 // ----------------------------------------------------------------------------
0009 // QT Includes
0010 
0011 #include <QApplication>
0012 #include <QRect>
0013 #include <QScreen>
0014 #include <QWidget>
0015 
0016 // ----------------------------------------------------------------------------
0017 // KDE Includes
0018 
0019 // ----------------------------------------------------------------------------
0020 // Project Includes
0021 
0022 
0023 PopupPositioner::PopupPositioner(QWidget* baseWidget, QWidget* popupWidget, Anchor anchor)
0024 {
0025     const auto screenRect = baseWidget->screen()->availableGeometry();
0026 
0027     auto p = baseWidget->mapToGlobal(QPoint());
0028     // align the y coordinate
0029     switch(anchor) {
0030     case BottemLeft:
0031     case BottomRight:
0032         if (p.y() + baseWidget->height() + popupWidget->height() > screenRect.bottomLeft().y()) {
0033             p.setY(p.y() - popupWidget->height());
0034         } else {
0035             p.setY(p.y() + baseWidget->height());
0036         }
0037         break;
0038     case TopLeft:
0039     case TopRight:
0040         if (p.y() - popupWidget->height() < screenRect.topLeft().y()) {
0041             p.setY(p.y() + baseWidget->height());
0042         } else {
0043             p.setY(p.y() - popupWidget->height());
0044         }
0045         break;
0046     }
0047 
0048     // align the x coordinate
0049     switch(anchor) {
0050     case BottemLeft:
0051     case TopLeft:
0052         // if left aligning causes the widget to leave the screen area
0053         // then align it to the right edge of the base widget instead
0054         if (p.x() + popupWidget->width() > screenRect.topRight().x()) {
0055             p.setX(p.x() + baseWidget->width() - popupWidget->width());
0056         }
0057         break;
0058 
0059     case BottomRight:
0060     case TopRight:
0061         // align to the right
0062         p.setX(p.x() + baseWidget->width() - popupWidget->width());
0063 
0064         // if right aligning causes the widget to leave the screen area
0065         // then align it to the left edge of the base widget
0066         if (p.x() < screenRect.topLeft().x()) {
0067             p.setX(baseWidget->x());
0068         }
0069         break;
0070     }
0071 
0072     // if the popup widget leaves the screen to the left
0073     // then align it to the left side of the screen
0074     if (p.x() < screenRect.topLeft().x()) {
0075         p.setX(screenRect.topLeft().x());
0076     }
0077     // if the popup widget leaves the screen to the right
0078     // then align its right edge to the right side of the screen
0079     if (p.x() + popupWidget->width() > screenRect.topRight().x()) {
0080         p.setX(screenRect.topRight().x() - popupWidget->width());
0081     }
0082 
0083     // move the popup widget to its location
0084     popupWidget->move(p);
0085 }