1 /*
2   overlaywidget.h
3 
4   This file is part of GammaRay, the Qt application inspection and
5   manipulation tool.
6 
7   Copyright (C) 2010-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8   Author: Tobias Koenig <tobias.koenig@kdab.com>
9 
10   Licensees holding valid commercial KDAB GammaRay licenses may use this file in
11   accordance with GammaRay Commercial License Agreement provided with the Software.
12 
13   Contact info@kdab.com if any conditions of this licensing are not clear to you.
14 
15   This program is free software; you can redistribute it and/or modify
16   it under the terms of the GNU General Public License as published by
17   the Free Software Foundation, either version 2 of the License, or
18   (at your option) any later version.
19 
20   This program is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24 
25   You should have received a copy of the GNU General Public License
26   along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 */
28 
29 #ifndef GAMMARAY_WIDGETINSPECTOR_OVERLAYWIDGET_H
30 #define GAMMARAY_WIDGETINSPECTOR_OVERLAYWIDGET_H
31 
32 #include <QLayout>
33 #include <QPainterPath>
34 #include <QPointer>
35 #include <QWidget>
36 
37 namespace GammaRay {
38 
39 class WidgetOrLayoutFacade
40 {
41 public:
WidgetOrLayoutFacade()42     WidgetOrLayoutFacade() : m_object(nullptr) {}
WidgetOrLayoutFacade(QWidget * widget)43     WidgetOrLayoutFacade(QWidget *widget) : m_object(widget) {} //krazy:exclude=explicit
WidgetOrLayoutFacade(QLayout * layout)44     WidgetOrLayoutFacade(QLayout *layout) : m_object(layout) {} //krazy:exclude=explicit
45 
46     /// Get either the layout of the widget or the this-pointer
layout()47     inline QLayout *layout() const
48     {
49         return isLayout() ? asLayout() : asWidget()->layout();
50     }
51 
52     /// Get either the parent widget of the layout or the this-pointer
widget()53     QWidget *widget() const
54     {
55         return isLayout() ? asLayout()->parentWidget() : asWidget();
56     }
57 
geometry()58     QRect geometry() const
59     {
60         return isLayout() ? asLayout()->geometry() : asWidget()->geometry();
61     }
62 
isVisible()63     bool isVisible() const
64     {
65         return widget() ? widget()->isVisible() && !widget()->isHidden() : false;
66     }
67 
pos()68     QPoint pos() const
69     {
70         return isLayout() ? asLayout()->geometry().topLeft() : QPoint(0, 0);
71     }
72 
isNull()73     inline bool isNull() const { return !m_object; }
data()74     inline QObject* data() { return m_object; }
75     inline QObject* operator->() const { Q_ASSERT(!isNull()); return m_object; }
clear()76     inline void clear() { m_object = nullptr; }
77 
78 private:
isLayout()79     inline bool isLayout() const { Q_ASSERT(!isNull()); return qobject_cast<QLayout *>(m_object); }
asLayout()80     inline QLayout *asLayout() const { return static_cast<QLayout *>(m_object.data()); }
asWidget()81     inline QWidget *asWidget() const { return static_cast<QWidget *>(m_object.data()); }
82 
83     QPointer<QObject> m_object;
84 };
85 
86 class OverlayWidget : public QWidget
87 {
88     Q_OBJECT
89 
90 public:
91     OverlayWidget();
92 
93     /**
94      * Place the overlay on @p item
95      *
96      * @param item The overlay can be cover a widget or a layout
97      */
98     void placeOn(const WidgetOrLayoutFacade &item);
99 
100     bool eventFilter(QObject *receiver, QEvent *event) override;
101 
102 protected:
103     void paintEvent(QPaintEvent *event) override;
104 
105 private:
106     void resizeOverlay();
107     void updatePositions();
108 
109     QWidget *m_currentToplevelWidget;
110     WidgetOrLayoutFacade m_currentItem;
111     QRect m_outerRect;
112     QColor m_outerRectColor;
113 
114     QPainterPath m_layoutPath;
115     bool m_drawLayoutOutlineOnly;
116 };
117 }
118 
119 #endif
120