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
40 QT_BEGIN_NAMESPACE
41
42 namespace qdesigner_internal {
43
QMdiAreaContainer(QMdiArea * widget,QObject * parent)44 QMdiAreaContainer::QMdiAreaContainer(QMdiArea *widget, QObject *parent)
45 : QObject(parent),
46 m_mdiArea(widget)
47 {
48 }
49
count() const50 int QMdiAreaContainer::count() const
51 {
52 return m_mdiArea->subWindowList(QMdiArea::CreationOrder).count();
53 }
54
widget(int index) const55 QWidget *QMdiAreaContainer::widget(int index) const
56 {
57 if (index < 0)
58 return nullptr;
59 return m_mdiArea->subWindowList(QMdiArea::CreationOrder).at(index)->widget();
60 }
61
currentIndex() const62 int QMdiAreaContainer::currentIndex() const
63 {
64 if (QMdiSubWindow *sub = m_mdiArea->activeSubWindow())
65 return m_mdiArea->subWindowList(QMdiArea::CreationOrder).indexOf(sub);
66 return -1;
67 }
68
setCurrentIndex(int index)69 void 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(QMdiArea::CreationOrder).at(index);
76 m_mdiArea->setActiveSubWindow(frame);
77 }
78
addWidget(QWidget * widget)79 void QMdiAreaContainer::addWidget(QWidget *widget)
80 {
81 QMdiSubWindow *frame = m_mdiArea->addSubWindow(widget, Qt::Window);
82 frame->show();
83 m_mdiArea->cascadeSubWindows();
84 positionNewMdiChild(m_mdiArea, frame);
85 }
86
87 // Semi-smart positioning of new windows: Make child fill the whole MDI window below
88 // cascaded other windows
positionNewMdiChild(const QWidget * area,QWidget * mdiChild)89 void 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(0, pos.y());
106 mdiChild->resize(fullSize);
107 }
108 }
109 break;
110 }
111 }
112
insertWidget(int,QWidget * widget)113 void QMdiAreaContainer::insertWidget(int, QWidget *widget)
114 {
115 addWidget(widget);
116 }
117
remove(int index)118 void QMdiAreaContainer::remove(int index)
119 {
120 auto subWins = m_mdiArea->subWindowList(QMdiArea::CreationOrder);
121 if (index >= 0 && index < subWins.size()) {
122 QMdiSubWindow *f = subWins.at(index);
123 m_mdiArea->removeSubWindow(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
132 static const char *subWindowTitleC = "activeSubWindowTitle";
133 static const char *subWindowNameC = "activeSubWindowName";
134
QMdiAreaPropertySheet(QWidget * mdiArea,QObject * parent)135 QMdiAreaPropertySheet::QMdiAreaPropertySheet(QWidget *mdiArea, QObject *parent) :
136 QDesignerPropertySheet(mdiArea, parent),
137 m_windowTitleProperty(QStringLiteral("windowTitle"))
138 {
139 createFakeProperty(QLatin1String(subWindowNameC), QString());
140 createFakeProperty(QLatin1String(subWindowTitleC), QString());
141 }
142
mdiAreaProperty(const QString & name)143 QMdiAreaPropertySheet::MdiAreaProperty QMdiAreaPropertySheet::mdiAreaProperty(const QString &name)
144 {
145 using MdiAreaPropertyHash = QHash<QString, MdiAreaProperty>;
146 static MdiAreaPropertyHash mdiAreaPropertyHash;
147 if (mdiAreaPropertyHash.isEmpty()) {
148 mdiAreaPropertyHash.insert(QLatin1String(subWindowNameC), MdiAreaSubWindowName);
149 mdiAreaPropertyHash.insert(QLatin1String(subWindowTitleC), MdiAreaSubWindowTitle);
150 }
151 return mdiAreaPropertyHash.value(name,MdiAreaNone);
152 }
153
setProperty(int index,const QVariant & value)154 void QMdiAreaPropertySheet::setProperty(int index, const QVariant &value)
155 {
156 switch (mdiAreaProperty(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(m_windowTitleProperty);
164 cws->setProperty(index, value);
165 cws->setChanged(index, true);
166 }
167 break;
168 default:
169 QDesignerPropertySheet::setProperty(index, value);
170 break;
171 }
172 }
173
reset(int index)174 bool QMdiAreaPropertySheet::reset(int index)
175 {
176 bool rc = true;
177 switch (mdiAreaProperty(propertyName(index))) {
178 case MdiAreaSubWindowName:
179 setProperty(index, QVariant(QString()));
180 setChanged(index, false);
181 break;
182 case MdiAreaSubWindowTitle: // Forward to window title of subwindow
183 if (QDesignerPropertySheetExtension *cws = currentWindowSheet()) {
184 const int index = cws->indexOf(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
property(int index) const195 QVariant QMdiAreaPropertySheet::property(int index) const
196 {
197 switch (mdiAreaProperty(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
isEnabled(int index) const212 bool QMdiAreaPropertySheet::isEnabled(int index) const
213 {
214 switch (mdiAreaProperty(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
isChanged(int index) const224 bool QMdiAreaPropertySheet::isChanged(int index) const
225 {
226 bool rc = false;
227 switch (mdiAreaProperty(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(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
currentWindow() const244 QWidget *QMdiAreaPropertySheet::currentWindow() const
245 {
246 if (const QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension*>(core()->extensionManager(), object())) {
247 const int ci = c->currentIndex();
248 if (ci < 0)
249 return nullptr;
250 return c->widget(ci);
251 }
252 return nullptr;
253 }
254
currentWindowSheet() const255 QDesignerPropertySheetExtension *QMdiAreaPropertySheet::currentWindowSheet() const
256 {
257 QWidget *cw = currentWindow();
258 if (cw == nullptr)
259 return nullptr;
260 return qt_extension<QDesignerPropertySheetExtension*>(core()->extensionManager(), cw);
261 }
262
checkProperty(const QString & propertyName)263 bool QMdiAreaPropertySheet::checkProperty(const QString &propertyName)
264 {
265 return mdiAreaProperty(propertyName) == MdiAreaNone;
266 }
267 }
268 QT_END_NAMESPACE
269