1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Designer of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "qmdiarea_container.h"
30
31#include <QtDesigner/qextensionmanager.h>
32#include <QtDesigner/abstractformeditor.h>
33
34#include <QtWidgets/qmdiarea.h>
35#include <QtWidgets/qmdisubwindow.h>
36#include <QtWidgets/qapplication.h>
37#include <QtCore/qdebug.h>
38#include <QtCore/qhash.h>
39
40QT_BEGIN_NAMESPACE
41
42namespace qdesigner_internal {
43
44QMdiAreaContainer::QMdiAreaContainer(QMdiArea *widget, QObject *parent)
45 : QObject(parent),
46 m_mdiArea(widget)
47{
48}
49
50int QMdiAreaContainer::count() const
51{
52 return m_mdiArea->subWindowList(order: QMdiArea::CreationOrder).count();
53}
54
55QWidget *QMdiAreaContainer::widget(int index) const
56{
57 if (index < 0)
58 return nullptr;
59 return m_mdiArea->subWindowList(order: QMdiArea::CreationOrder).at(i: index)->widget();
60}
61
62int QMdiAreaContainer::currentIndex() const
63{
64 if (QMdiSubWindow *sub = m_mdiArea->activeSubWindow())
65 return m_mdiArea->subWindowList(order: QMdiArea::CreationOrder).indexOf(t: sub);
66 return -1;
67}
68
69void QMdiAreaContainer::setCurrentIndex(int index)
70{
71 if (index < 0) {
72 qDebug() << "** WARNING Attempt to QMdiAreaContainer::setCurrentIndex(-1)";
73 return;
74 }
75 QMdiSubWindow *frame = m_mdiArea->subWindowList(order: QMdiArea::CreationOrder).at(i: index);
76 m_mdiArea->setActiveSubWindow(frame);
77}
78
79void QMdiAreaContainer::addWidget(QWidget *widget)
80{
81 QMdiSubWindow *frame = m_mdiArea->addSubWindow(widget, flags: Qt::Window);
82 frame->show();
83 m_mdiArea->cascadeSubWindows();
84 positionNewMdiChild(area: m_mdiArea, mdiChild: frame);
85}
86
87// Semi-smart positioning of new windows: Make child fill the whole MDI window below
88// cascaded other windows
89void QMdiAreaContainer::positionNewMdiChild(const QWidget *area, QWidget *mdiChild)
90{
91 enum { MinSize = 20 };
92 const QPoint pos = mdiChild->pos();
93 const QSize areaSize = area->size();
94 switch (QApplication::layoutDirection()) {
95 case Qt::LayoutDirectionAuto:
96 case Qt::LeftToRight: {
97 const QSize fullSize = QSize(areaSize.width() - pos.x(), areaSize.height() - pos.y());
98 if (fullSize.width() > MinSize && fullSize.height() > MinSize)
99 mdiChild->resize(fullSize);
100 }
101 break;
102 case Qt::RightToLeft: {
103 const QSize fullSize = QSize(pos.x() + mdiChild->width(), areaSize.height() - pos.y());
104 if (fullSize.width() > MinSize && fullSize.height() > MinSize) {
105 mdiChild->move(ax: 0, ay: pos.y());
106 mdiChild->resize(fullSize);
107 }
108 }
109 break;
110 }
111}
112
113void QMdiAreaContainer::insertWidget(int, QWidget *widget)
114{
115 addWidget(widget);
116}
117
118void QMdiAreaContainer::remove(int index)
119{
120 auto subWins = m_mdiArea->subWindowList(order: QMdiArea::CreationOrder);
121 if (index >= 0 && index < subWins.size()) {
122 QMdiSubWindow *f = subWins.at(i: index);
123 m_mdiArea->removeSubWindow(widget: f->widget());
124 delete f;
125 }
126}
127
128// ---------- MdiAreaPropertySheet, creates fake properties:
129// 1) window name (object name of child)
130// 2) title (windowTitle of child).
131
132static const char *subWindowTitleC = "activeSubWindowTitle";
133static const char *subWindowNameC = "activeSubWindowName";
134
135QMdiAreaPropertySheet::QMdiAreaPropertySheet(QWidget *mdiArea, QObject *parent) :
136 QDesignerPropertySheet(mdiArea, parent),
137 m_windowTitleProperty(QStringLiteral("windowTitle"))
138{
139 createFakeProperty(propertyName: QLatin1String(subWindowNameC), value: QString());
140 createFakeProperty(propertyName: QLatin1String(subWindowTitleC), value: QString());
141}
142
143QMdiAreaPropertySheet::MdiAreaProperty QMdiAreaPropertySheet::mdiAreaProperty(const QString &name)
144{
145 using MdiAreaPropertyHash = QHash<QString, MdiAreaProperty>;
146 static MdiAreaPropertyHash mdiAreaPropertyHash;
147 if (mdiAreaPropertyHash.isEmpty()) {
148 mdiAreaPropertyHash.insert(akey: QLatin1String(subWindowNameC), avalue: MdiAreaSubWindowName);
149 mdiAreaPropertyHash.insert(akey: QLatin1String(subWindowTitleC), avalue: MdiAreaSubWindowTitle);
150 }
151 return mdiAreaPropertyHash.value(akey: name,adefaultValue: MdiAreaNone);
152}
153
154void QMdiAreaPropertySheet::setProperty(int index, const QVariant &value)
155{
156 switch (mdiAreaProperty(name: propertyName(index))) {
157 case MdiAreaSubWindowName:
158 if (QWidget *w = currentWindow())
159 w->setObjectName(value.toString());
160 break;
161 case MdiAreaSubWindowTitle: // Forward to window title of subwindow
162 if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
163 const int index = cws->indexOf(name: m_windowTitleProperty);
164 cws->setProperty(index, value);
165 cws->setChanged(index, changed: true);
166 }
167 break;
168 default:
169 QDesignerPropertySheet::setProperty(index, value);
170 break;
171 }
172}
173
174bool QMdiAreaPropertySheet::reset(int index)
175{
176 bool rc = true;
177 switch (mdiAreaProperty(name: propertyName(index))) {
178 case MdiAreaSubWindowName:
179 setProperty(index, value: QVariant(QString()));
180 setChanged(index, changed: false);
181 break;
182 case MdiAreaSubWindowTitle: // Forward to window title of subwindow
183 if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
184 const int index = cws->indexOf(name: m_windowTitleProperty);
185 rc = cws->reset(index);
186 }
187 break;
188 default:
189 rc = QDesignerPropertySheet::reset(index);
190 break;
191 }
192 return rc;
193}
194
195QVariant QMdiAreaPropertySheet::property(int index) const
196{
197 switch (mdiAreaProperty(name: propertyName(index))) {
198 case MdiAreaSubWindowName:
199 if (QWidget *w = currentWindow())
200 return w->objectName();
201 return QVariant(QString());
202 case MdiAreaSubWindowTitle:
203 if (QWidget *w = currentWindow())
204 return w->windowTitle();
205 return QVariant(QString());
206 case MdiAreaNone:
207 break;
208 }
209 return QDesignerPropertySheet::property(index);
210}
211
212bool QMdiAreaPropertySheet::isEnabled(int index) const
213{
214 switch (mdiAreaProperty(name: propertyName(index))) {
215 case MdiAreaSubWindowName:
216 case MdiAreaSubWindowTitle:
217 return currentWindow() != nullptr;
218 case MdiAreaNone:
219 break;
220 }
221 return QDesignerPropertySheet::isEnabled(index);
222}
223
224bool QMdiAreaPropertySheet::isChanged(int index) const
225{
226 bool rc = false;
227 switch (mdiAreaProperty(name: propertyName(index))) {
228 case MdiAreaSubWindowName:
229 rc = currentWindow() != nullptr;
230 break;
231 case MdiAreaSubWindowTitle:
232 if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
233 const int index = cws->indexOf(name: m_windowTitleProperty);
234 rc = cws->isChanged(index);
235 }
236 break;
237 default:
238 rc = QDesignerPropertySheet::isChanged(index);
239 break;
240 }
241 return rc;
242}
243
244QWidget *QMdiAreaPropertySheet::currentWindow() const
245{
246 if (const QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(manager: core()->extensionManager(), object: object())) {
247 const int ci = c->currentIndex();
248 if (ci < 0)
249 return nullptr;
250 return c->widget(index: ci);
251 }
252 return nullptr;
253}
254
255QDesignerPropertySheetExtension *QMdiAreaPropertySheet::currentWindowSheet() const
256{
257 QWidget *cw = currentWindow();
258 if (cw == nullptr)
259 return nullptr;
260 return qt_extension<QDesignerPropertySheetExtension*>(manager: core()->extensionManager(), object: cw);
261}
262
263bool QMdiAreaPropertySheet::checkProperty(const QString &propertyName)
264{
265 return mdiAreaProperty(name: propertyName) == MdiAreaNone;
266}
267}
268QT_END_NAMESPACE
269

source code of qttools/src/designer/src/components/formeditor/qmdiarea_container.cpp