File indexing completed on 2024-05-19 04:29:18

0001 /*
0002  *  SPDX-FileCopyrightText: 2021 Emmet O 'Neill <emmetoneill.pdx@gmail.com>
0003  *  SPDX-FileCopyrightText: 2021 Eoin O 'Neill <eoinoneill1991@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #ifndef KISPOPUPWIDGETINTERFACE_H
0009 #define KISPOPUPWIDGETINTERFACE_H
0010 
0011 #include <QWidget>
0012 #include <QGridLayout>
0013 
0014 #include "kis_debug.h"
0015 #include "kis_assert.h"
0016 
0017 #include "KoCanvasBase.h"
0018 #include "input/kis_input_manager.h"
0019 
0020 /**
0021  * @brief The PopupWidgetInterface abstract class defines
0022  * the basic interface that will be used by all popup widgets.
0023  *
0024  * Classes that implement this interface should use `Q_INTERFACES(KisPopupWidgetInterface)`!
0025  * This is needed in order to include signals in the interface.
0026  */
0027 class KisPopupWidgetInterface {
0028 public:
0029     virtual ~KisPopupWidgetInterface() {}
0030 
0031     /**
0032      * @brief Called when and where you want a widget to popup.
0033      */
0034     virtual void popup(const QPoint& position) = 0;
0035 
0036     /**
0037      * @brief Returns whether the widget is active (on screen) or not.
0038      */
0039     virtual bool onScreen() = 0;
0040 
0041     /**
0042      * @brief Called when you want to dismiss a popup widget.
0043      */
0044     virtual void dismiss() = 0;
0045 
0046 Q_SIGNALS:
0047     /**
0048      * @brief Emitted when a popup widget believes that its job is finished.
0049      */
0050     virtual void finished() = 0;
0051 };
0052 
0053 Q_DECLARE_INTERFACE(KisPopupWidgetInterface, "KisPopupWidgetInterface")
0054 
0055 //===================================================================================
0056 
0057 /**
0058  * @brief The KisPopupWidget class is a simple wrapper that
0059  * turns any QWidget into a popup widget that can be temporarily
0060  * displayed over the canvas.
0061  */
0062 class KisPopupWidget : public QWidget, public KisPopupWidgetInterface
0063 {
0064     Q_OBJECT
0065     Q_INTERFACES(KisPopupWidgetInterface)
0066 
0067 public:
0068     KisPopupWidget(QWidget* toPopup, KoCanvasBase* canvas)
0069         : QWidget(canvas->canvasWidget())
0070     {
0071         KIS_ASSERT(toPopup);
0072 
0073         m_toPopup = toPopup;
0074         m_toPopup->setParent(this);
0075 
0076         setLayout(new QGridLayout());
0077         layout()->addWidget(m_toPopup);
0078 
0079         setAutoFillBackground(true);
0080     }
0081 
0082     void popup(const QPoint& position) override {
0083         setVisible(true);
0084         adjustPopupLayout(position);
0085     }
0086 
0087     void dismiss() override {
0088         setVisible(false);
0089     }
0090 
0091     bool onScreen() override {
0092         return isVisible();
0093     }
0094 
0095     void adjustPopupLayout(const QPoint& position) {
0096         if (isVisible() && parentWidget())  {
0097             const float widgetMargin = -20.0f;
0098             const QRect fitRect = kisGrowRect(parentWidget()->rect(), widgetMargin);
0099             const QPoint paletteCenterOffset(sizeHint().width() / 2, sizeHint().height() / 2);
0100 
0101             QRect paletteRect = rect();
0102 
0103             paletteRect.moveTo(position - paletteCenterOffset);
0104 
0105             paletteRect = kisEnsureInRect(paletteRect, fitRect);
0106             move(paletteRect.topLeft());
0107         }
0108     }
0109 
0110     QSize sizeHint() const override {
0111         KIS_ASSERT(m_toPopup);
0112         return m_toPopup->sizeHint();
0113     }
0114 
0115 private:
0116     QWidget* m_toPopup;
0117 };
0118 
0119 #endif // KISPOPUPWIDGETINTERFACE_H