1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QMDISUBWINDOW_P_H |
5 | #define QMDISUBWINDOW_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtWidgets/private/qtwidgetsglobal_p.h> |
19 | #include "qmdisubwindow.h" |
20 | |
21 | #include <QStyle> |
22 | #include <QStyleOptionTitleBar> |
23 | #if QT_CONFIG(menubar) |
24 | #include <QMenuBar> |
25 | #endif |
26 | #if QT_CONFIG(sizegrip) |
27 | #include <QSizeGrip> |
28 | #endif |
29 | #include <QPointer> |
30 | #include <QDebug> |
31 | #include <private/qwidget_p.h> |
32 | |
33 | QT_REQUIRE_CONFIG(mdiarea); |
34 | |
35 | QT_BEGIN_NAMESPACE |
36 | |
37 | class QVBoxLayout; |
38 | class QMouseEvent; |
39 | |
40 | namespace QMdi { |
41 | template<typename T> |
42 | class ControlElement : public T // ELFVERSION:ignore |
43 | { |
44 | public: |
45 | ControlElement(QMdiSubWindow *child) : T(child, nullptr) |
46 | { |
47 | Q_ASSERT(child); |
48 | mdiChild = child; |
49 | } |
50 | |
51 | void *qt_metacast(const char *classname) override |
52 | { |
53 | if (classname && strcmp(s1: classname, s2: "ControlElement" ) == 0) |
54 | return this; |
55 | return nullptr; |
56 | } |
57 | |
58 | QPointer<QMdiSubWindow> mdiChild; |
59 | }; |
60 | |
61 | class ControlContainer : public QObject // ELFVERSION:ignore |
62 | { |
63 | public: |
64 | ControlContainer(QMdiSubWindow *mdiChild); |
65 | ~ControlContainer(); |
66 | |
67 | #if QT_CONFIG(menubar) |
68 | void (QMenuBar *); |
69 | void (QMenuBar * = nullptr); |
70 | QMenuBar *() const { return m_menuBar; } |
71 | #endif |
72 | void updateWindowIcon(const QIcon &windowIcon); |
73 | QWidget *controllerWidget() const { return m_controllerWidget; } |
74 | QWidget *() const { return m_menuLabel; } |
75 | |
76 | private: |
77 | QPointer<QWidget> previousLeft; |
78 | QPointer<QWidget> previousRight; |
79 | #if QT_CONFIG(menubar) |
80 | QPointer<QMenuBar> ; |
81 | #endif |
82 | QPointer<QWidget> m_controllerWidget; |
83 | QPointer<QWidget> ; |
84 | QPointer<QMdiSubWindow> mdiChild; |
85 | }; |
86 | } // namespace QMdi |
87 | |
88 | class Q_AUTOTEST_EXPORT QMdiSubWindowPrivate : public QWidgetPrivate |
89 | { |
90 | Q_DECLARE_PUBLIC(QMdiSubWindow) |
91 | public: |
92 | // Enums and typedefs. |
93 | enum Operation { |
94 | None, |
95 | Move, |
96 | TopResize, |
97 | BottomResize, |
98 | LeftResize, |
99 | RightResize, |
100 | TopLeftResize, |
101 | TopRightResize, |
102 | BottomLeftResize, |
103 | BottomRightResize |
104 | }; |
105 | |
106 | enum ChangeFlag { |
107 | HMove = 0x01, |
108 | VMove = 0x02, |
109 | HResize = 0x04, |
110 | VResize = 0x08, |
111 | HResizeReverse = 0x10, |
112 | VResizeReverse = 0x20 |
113 | }; |
114 | |
115 | enum WindowStateAction { |
116 | RestoreAction, |
117 | MoveAction, |
118 | ResizeAction, |
119 | MinimizeAction, |
120 | MaximizeAction, |
121 | StayOnTopAction, |
122 | CloseAction, |
123 | /* Add new states _above_ this line! */ |
124 | NumWindowStateActions |
125 | }; |
126 | |
127 | struct OperationInfo { |
128 | uint changeFlags; |
129 | Qt::CursorShape cursorShape; |
130 | QRegion region; |
131 | bool hover; |
132 | OperationInfo(uint changeFlags, Qt::CursorShape cursorShape, bool hover = true) |
133 | : changeFlags(changeFlags), |
134 | cursorShape(cursorShape), |
135 | hover(hover) |
136 | {} |
137 | }; |
138 | |
139 | typedef QMap<Operation, OperationInfo> OperationInfoMap; |
140 | |
141 | QMdiSubWindowPrivate(); |
142 | |
143 | // Variables. |
144 | QPointer<QWidget> baseWidget; |
145 | QPointer<QWidget> restoreFocusWidget; |
146 | QPointer<QMdi::ControlContainer> controlContainer; |
147 | #if QT_CONFIG(sizegrip) |
148 | QPointer<QSizeGrip> sizeGrip; |
149 | #endif |
150 | #if QT_CONFIG(rubberband) |
151 | QRubberBand *rubberBand; |
152 | #endif |
153 | QPoint mousePressPosition; |
154 | QRect oldGeometry; |
155 | QSize internalMinimumSize; |
156 | QSize userMinimumSize; |
157 | QSize restoreSize; |
158 | bool resizeEnabled; |
159 | bool moveEnabled; |
160 | bool isInInteractiveMode; |
161 | #if QT_CONFIG(rubberband) |
162 | bool isInRubberBandMode; |
163 | #endif |
164 | bool isShadeMode; |
165 | bool ignoreWindowTitleChange; |
166 | bool ignoreNextActivationEvent; |
167 | bool activationEnabled; |
168 | bool isShadeRequestFromMinimizeMode; |
169 | bool isMaximizeMode; |
170 | bool isWidgetHiddenByUs; |
171 | bool isActive; |
172 | bool isExplicitlyDeactivated; |
173 | int keyboardSingleStep; |
174 | int keyboardPageStep; |
175 | int resizeTimerId; |
176 | Operation currentOperation; |
177 | QStyle::SubControl hoveredSubControl; |
178 | QStyle::SubControl activeSubControl; |
179 | Qt::FocusReason focusInReason; |
180 | OperationInfoMap operationMap; |
181 | QPointer<QMenu> ; |
182 | #ifndef QT_NO_ACTION |
183 | QPointer<QAction> actions[NumWindowStateActions]; |
184 | #endif |
185 | QMdiSubWindow::SubWindowOptions options; |
186 | QString lastChildWindowTitle; |
187 | QPalette titleBarPalette; |
188 | QString windowTitle; |
189 | QFont font; |
190 | QIcon ; |
191 | QStyleOptionTitleBar cachedStyleOptions; |
192 | QString originalTitle; |
193 | |
194 | // Slots. |
195 | void _q_updateStaysOnTopHint(); |
196 | void _q_enterInteractiveMode(); |
197 | void _q_processFocusChanged(QWidget *old, QWidget *now); |
198 | |
199 | // Functions. |
200 | void leaveInteractiveMode(); |
201 | void removeBaseWidget(); |
202 | void initOperationMap(); |
203 | #if QT_CONFIG(menu) |
204 | void (); |
205 | #endif |
206 | void updateCursor(); |
207 | void updateDirtyRegions(); |
208 | void updateGeometryConstraints(); |
209 | void updateMask(); |
210 | void setNewGeometry(const QPoint &pos); |
211 | void setMinimizeMode(); |
212 | void setNormalMode(); |
213 | void setMaximizeMode(); |
214 | void setActive(bool activate, bool changeFocus = true); |
215 | void processClickedSubControl(); |
216 | QRegion getRegion(Operation operation) const; |
217 | Operation getOperation(const QPoint &pos) const; |
218 | QStyleOptionTitleBar titleBarOptions() const; |
219 | void ensureWindowState(Qt::WindowState state); |
220 | int titleBarHeight(const QStyleOptionTitleBar &options) const; |
221 | void sizeParameters(int *margin, int *minWidth) const; |
222 | bool drawTitleBarWhenMaximized() const; |
223 | #if QT_CONFIG(menubar) |
224 | QMenuBar *() const; |
225 | void (QMenuBar *); |
226 | void (); |
227 | #endif |
228 | void updateWindowTitle(bool requestFromChild); |
229 | #if QT_CONFIG(rubberband) |
230 | void enterRubberBandMode(); |
231 | void leaveRubberBandMode(); |
232 | #endif |
233 | QPalette desktopPalette() const; |
234 | void updateActions(); |
235 | void setFocusWidget(); |
236 | bool restoreFocus(); |
237 | void storeFocusWidget(); |
238 | void setWindowFlags(Qt::WindowFlags windowFlags) override; |
239 | void setVisible(WindowStateAction, bool visible = true); |
240 | #ifndef QT_NO_ACTION |
241 | void setEnabled(WindowStateAction, bool enable = true); |
242 | #if QT_CONFIG(menu) |
243 | void (WindowStateAction, const QString &text, const char *slot); |
244 | #endif |
245 | #endif // QT_NO_ACTION |
246 | QSize iconSize() const; |
247 | #if QT_CONFIG(sizegrip) |
248 | void setSizeGrip(QSizeGrip *sizeGrip); |
249 | void setSizeGripVisible(bool visible = true) const; |
250 | #endif |
251 | void updateInternalWindowTitle(); |
252 | QString originalWindowTitle(); |
253 | QString originalWindowTitleHelper() const; |
254 | void setNewWindowTitle(); |
255 | |
256 | inline int titleBarHeight() const |
257 | { |
258 | Q_Q(const QMdiSubWindow); |
259 | if (!parent || q->windowFlags() & Qt::FramelessWindowHint |
260 | || (q->isMaximized() && !drawTitleBarWhenMaximized())) { |
261 | return 0; |
262 | } |
263 | QStyleOptionTitleBar options = titleBarOptions(); |
264 | int height = options.rect.height(); |
265 | if (hasBorder(options)) |
266 | height += q->isMinimized() ? 8 : 4; |
267 | return height; |
268 | } |
269 | |
270 | inline QStyle::SubControl getSubControl(const QPoint &pos) const |
271 | { |
272 | Q_Q(const QMdiSubWindow); |
273 | QStyleOptionTitleBar titleBarOptions = this->titleBarOptions(); |
274 | return q->style()->hitTestComplexControl(cc: QStyle::CC_TitleBar, opt: &titleBarOptions, pt: pos, widget: q); |
275 | } |
276 | |
277 | inline void setNewGeometry(QRect *geometry) |
278 | { |
279 | Q_Q(QMdiSubWindow); |
280 | Q_ASSERT(parent); |
281 | geometry->setSize(geometry->size().expandedTo(otherSize: internalMinimumSize)); |
282 | #if QT_CONFIG(rubberband) |
283 | if (isInRubberBandMode) |
284 | rubberBand->setGeometry(*geometry); |
285 | else |
286 | #endif |
287 | q->setGeometry(*geometry); |
288 | } |
289 | |
290 | inline bool hasBorder(const QStyleOptionTitleBar &options) const |
291 | { |
292 | Q_Q(const QMdiSubWindow); |
293 | return !q->style()->styleHint(stylehint: QStyle::SH_TitleBar_NoBorder, opt: &options, widget: q); |
294 | } |
295 | |
296 | inline bool autoRaise() const |
297 | { |
298 | Q_Q(const QMdiSubWindow); |
299 | return q->style()->styleHint(stylehint: QStyle::SH_TitleBar_AutoRaise, opt: nullptr, widget: q); |
300 | } |
301 | |
302 | inline bool isResizeOperation() const |
303 | { |
304 | return currentOperation != None && currentOperation != Move; |
305 | } |
306 | |
307 | inline bool isMoveOperation() const |
308 | { |
309 | return currentOperation == Move; |
310 | } |
311 | }; |
312 | |
313 | QT_END_NAMESPACE |
314 | |
315 | #endif // QMDISUBWINDOW_P_H |
316 | |