File indexing completed on 2024-05-12 16:44:05

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 <QDesktopWidget>
0013 #include <QScreen>
0014 #include <QWidget>
0015 #include <QRect>
0016 
0017 // ----------------------------------------------------------------------------
0018 // KDE Includes
0019 
0020 // ----------------------------------------------------------------------------
0021 // Project Includes
0022 
0023 
0024 PopupPositioner::PopupPositioner(QWidget* baseWidget, QWidget* popupWidget, Anchor anchor)
0025 {
0026     // the following two lines use deprecated functions. I have not yet
0027     // found out how to obtain the same information with newer versions (> 5.14)
0028     auto screenNr = QApplication::desktop()->screenNumber(baseWidget);
0029     const auto screenRect = QApplication::desktop()->screenGeometry(screenNr);
0030 
0031     auto p = baseWidget->mapToGlobal(QPoint());
0032     // align the y coordinate
0033     switch(anchor) {
0034     case BottemLeft:
0035     case BottomRight:
0036         if (p.y() + baseWidget->height() + popupWidget->height() > screenRect.bottomLeft().y()) {
0037             p.setY(p.y() - popupWidget->height());
0038         } else {
0039             p.setY(p.y() + baseWidget->height());
0040         }
0041         break;
0042     case TopLeft:
0043     case TopRight:
0044         if (p.y() - popupWidget->height() < screenRect.topLeft().y()) {
0045             p.setY(p.y() + baseWidget->height());
0046         } else {
0047             p.setY(p.y() - popupWidget->height());
0048         }
0049         break;
0050     }
0051 
0052     // align the x coordinate
0053     switch(anchor) {
0054     case BottemLeft:
0055     case TopLeft:
0056         // if left aligning causes the widget to leave the screen area
0057         // then align it to the right edge of the base widget instead
0058         if (p.x() + popupWidget->width() > screenRect.topRight().x()) {
0059             p.setX(p.x() + baseWidget->width() - popupWidget->width());
0060         }
0061         break;
0062 
0063     case BottomRight:
0064     case TopRight:
0065         // align to the right
0066         p.setX(p.x() + baseWidget->width() - popupWidget->width());
0067 
0068         // if right aligning causes the widget to leave the screen area
0069         // then align it to the left edge of the base widget
0070         if (p.x() < screenRect.topLeft().x()) {
0071             p.setX(baseWidget->x());
0072         }
0073         break;
0074     }
0075 
0076     // if the popup widget leaves the screen to the left
0077     // then align it to the left side of the screen
0078     if (p.x() < screenRect.topLeft().x()) {
0079         p.setX(screenRect.topLeft().x());
0080     }
0081     // if the popup widget leaves the screen to the right
0082     // then align its right edge to the right side of the screen
0083     if (p.x() + popupWidget->width() > screenRect.topRight().x()) {
0084         p.setX(screenRect.topRight().x() - popupWidget->width());
0085     }
0086 
0087     // move the popup widget to its location
0088     popupWidget->move(p);
0089 }