1 /*****************************************************************************
2  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
3  *                                                                           *
4  *   This program is free software; you can redistribute it and/or modify    *
5  *   it under the terms of the GNU Lesser General Public License as          *
6  *   published by the Free Software Foundation; either version 2.1 of the    *
7  *   License, or (at your option) version 3, or any later version accepted   *
8  *   by the membership of KDE e.V. (or its successor approved by the         *
9  *   membership of KDE e.V.), which shall act as a proxy defined in          *
10  *   Section 6 of version 3 of the license.                                  *
11  *                                                                           *
12  *   This program is distributed in the hope that it will be useful,         *
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
15  *   Lesser General Public License for more details.                         *
16  *                                                                           *
17  *   You should have received a copy of the GNU Lesser General Public        *
18  *   License along with this library. If not,                                *
19  *   see <http://www.gnu.org/licenses/>.                                     *
20  *****************************************************************************/
21 
22 #ifndef __QTC_UTILS_QT_UTILS_H__
23 #define __QTC_UTILS_QT_UTILS_H__
24 
25 #include "utils.h"
26 #include <QtGlobal>
27 #include <QWidget>
28 #include <config.h>
29 #include <QStyleOption>
30 #include <QObject>
31 #include <QRect>
32 
33 namespace QtCurve {
34 
35 #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0) && defined QTC_QT4_ENABLE_KDE) || \
36     (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && defined QTC_QT5_ENABLE_KDE)
37 #define _QTC_QT_ENABLE_KDE 1
38 #else
39 #define _QTC_QT_ENABLE_KDE 0
40 #endif
41 
42 #define qtcCheckKDEType(obj, type) (qtcCheckKDETypeFull(obj, type, #type))
43 
44 template<typename T, typename T2>
45 QTC_ALWAYS_INLINE static inline const T*
qtcObjCast(const T2 * obj)46 qtcObjCast(const T2 *obj)
47 {
48     return obj ? qobject_cast<const T*>(obj) : nullptr;
49 }
50 template<typename T, typename T2>
51 QTC_ALWAYS_INLINE static inline T*
qtcObjCast(T2 * obj)52 qtcObjCast(T2 *obj)
53 {
54     return obj ? qobject_cast<T*>(obj) : nullptr;
55 }
56 
57 template <class T, class T2> static inline bool
qtcCheckType(T2 * obj)58 qtcCheckType(T2 *obj)
59 {
60     return qtcObjCast<T>(obj);
61 }
62 template <class T2> static inline bool
qtcCheckType(T2 * obj,const char * name)63 qtcCheckType(T2 *obj, const char *name)
64 {
65     return obj && obj->inherits(name);
66 }
67 
68 #if _QTC_QT_ENABLE_KDE
69 #define qtcCheckKDETypeFull(obj, type, name) (qtcCheckType<type>(obj))
70 #else
71 #define qtcCheckKDETypeFull(obj, type, name) (qtcCheckType(obj, name))
72 #endif
73 
74 QTC_ALWAYS_INLINE static inline WId
qtcGetWid(const QWidget * w)75 qtcGetWid(const QWidget *w)
76 {
77     if (!(w && w->testAttribute(Qt::WA_WState_Created))) {
78         return (WId)0;
79     }
80     return w->internalWinId();
81 }
82 
83 QTC_ALWAYS_INLINE static inline Qt::WindowType
qtcGetWindowType(const QWidget * w)84 qtcGetWindowType(const QWidget *w)
85 {
86     return w ? w->windowType() : (Qt::WindowType)0;
87 }
88 
89 QTC_ALWAYS_INLINE static inline bool
qtcIsDialog(const QWidget * w)90 qtcIsDialog(const QWidget *w)
91 {
92     return oneOf(qtcGetWindowType(w), Qt::Dialog, Qt::Sheet);
93 }
94 
95 QTC_ALWAYS_INLINE static inline bool
qtcIsWindow(const QWidget * w)96 qtcIsWindow(const QWidget *w)
97 {
98     return oneOf(qtcGetWindowType(w), Qt::Window);
99 }
100 
101 QTC_ALWAYS_INLINE static inline bool
qtcIsToolTip(const QWidget * w)102 qtcIsToolTip(const QWidget *w)
103 {
104     return oneOf(qtcGetWindowType(w), Qt::Tool, Qt::SplashScreen,
105                  Qt::ToolTip, Qt::Drawer);
106 }
107 
108 QTC_ALWAYS_INLINE static inline bool
qtcIsPopup(const QWidget * w)109 qtcIsPopup(const QWidget *w)
110 {
111     return oneOf(qtcGetWindowType(w), Qt::Popup);
112 }
113 
114 QTC_ALWAYS_INLINE static inline QWidget*
qtcToWidget(QObject * obj)115 qtcToWidget(QObject *obj)
116 {
117     if (obj->isWidgetType()) {
118         return static_cast<QWidget*>(obj);
119     }
120     return nullptr;
121 }
122 
123 QTC_ALWAYS_INLINE static inline const QWidget*
qtcToWidget(const QObject * obj)124 qtcToWidget(const QObject *obj)
125 {
126     if (obj->isWidgetType()) {
127         return static_cast<const QWidget*>(obj);
128     }
129     return nullptr;
130 }
131 
132 class Style;
133 template<class StyleType=Style, class C>
134 static inline StyleType*
getStyle(const C * obj)135 getStyle(const C *obj)
136 {
137     QStyle *style = obj->style();
138     return style ? qobject_cast<StyleType*>(style) : 0;
139 }
140 
141 // Get the width and direction of the arrow in a QBalloonTip
142 QTC_ALWAYS_INLINE static inline int
qtcGetBalloonMargin(QWidget * widget,bool * atTop)143 qtcGetBalloonMargin(QWidget *widget, bool *atTop)
144 {
145     int topMargin = 0;
146     int bottomMargin = 0;
147     widget->getContentsMargins(nullptr, &topMargin, nullptr, &bottomMargin);
148     if (topMargin > bottomMargin) {
149         *atTop = true;
150         return topMargin - bottomMargin;
151     } else {
152         *atTop = false;
153         return bottomMargin - topMargin;
154     }
155 }
156 
157 template<typename T, typename T2>
158 QTC_ALWAYS_INLINE static inline const T*
styleOptCast(const T2 * opt)159 styleOptCast(const T2 *opt)
160 {
161     return qstyleoption_cast<const T*>(opt);
162 }
163 
164 template<typename T, typename T2>
165 QTC_ALWAYS_INLINE static inline T*
styleOptCast(T2 * opt)166 styleOptCast(T2 *opt)
167 {
168     return qstyleoption_cast<T*>(opt);
169 }
170 
171 template<unsigned level=1>
172 QTC_ALWAYS_INLINE static inline QWidget*
getParent(const QWidget * w)173 getParent(const QWidget *w)
174 {
175     if (const QWidget *parent = getParent<level - 1>(w)) {
176         return parent->parentWidget();
177     }
178     return nullptr;
179 }
180 
181 template<>
182 inline QWidget*
183 getParent<0>(const QWidget *w)
184 {
185     return const_cast<QWidget*>(w);
186 }
187 
188 template<unsigned level=1>
189 QTC_ALWAYS_INLINE static inline QObject*
getParent(const QObject * o)190 getParent(const QObject *o)
191 {
192     if (const QObject *parent = getParent<level - 1>(o)) {
193         return parent->parent();
194     }
195     return nullptr;
196 }
197 
198 template<>
199 inline QObject*
200 getParent<0>(const QObject *o)
201 {
202     return const_cast<QObject*>(o);
203 }
204 
205 #define _qtcSlotWithTypes(self, name, types)                    \
206     self, static_cast<void(qtcPtrType<decltype(self)>::*)types> \
207         (qtcMemPtr(self, name))
208 
209 #define _qtcSlotWithoutTypes(self, name)        \
210     self, qtcMemPtr(self, name)
211 
212 #define qtcSlot(self, name, types...)                           \
213     QTC_SWITCH(types, _qtcSlotWithTypes, _qtcSlotWithoutTypes)  \
214     (self, name, ##types)
215 
centerRect(const QRect & rect,int width,int height)216 static inline QRect centerRect(const QRect &rect, int width, int height)
217 {
218     return QRect(rect.left() + (rect.width() - width) / 2,
219                  rect.top() + (rect.height() - height) / 2, width, height);
220 }
221 
centerRect(const QRect & rect,const QSize & size)222 static inline QRect centerRect(const QRect &rect, const QSize &size)
223 {
224     return centerRect(rect, size.width(), size.height());
225 }
226 
227 }
228 
229 #endif
230