Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
widgetfactory.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
// Qt-Security score:significant reason:default
4
5
#
include
"widgetfactory_p.h"
6
#
include
"widgetdatabase_p.h"
7
#
include
"metadatabase_p.h"
8
#
include
"qlayout_widget_p.h"
9
#
include
"qdesigner_widget_p.h"
10
#
include
"qdesigner_tabwidget_p.h"
11
#
include
"qdesigner_toolbox_p.h"
12
#
include
"qdesigner_stackedbox_p.h"
13
#
include
"qdesigner_toolbar_p.h"
14
#
include
"qdesigner_menubar_p.h"
15
#
include
"qdesigner_menu_p.h"
16
#
include
"qdesigner_dockwidget_p.h"
17
#
include
"qdesigner_utils_p.h"
18
#
include
"formwindowbase_p.h"
19
#
include
"objectutils_p.h"
20
21
// shared
22
#
include
"layoutinfo_p.h"
23
#
include
"spacer_widget_p.h"
24
#
include
"layout_p.h"
25
#
include
"abstractintrospection_p.h"
26
27
// sdk
28
#
include
<
QtDesigner
/
abstractformeditor
.
h
>
29
#
include
<
QtDesigner
/
container
.
h
>
30
#
include
<
QtDesigner
/
qextensionmanager
.
h
>
31
#
include
<
QtDesigner
/
propertysheet
.
h
>
32
#
include
<
QtDesigner
/
abstractlanguage
.
h
>
33
#
include
<
QtDesigner
/
abstractformwindowmanager
.
h
>
34
#
include
<
QtDesigner
/
abstractformwindowcursor
.
h
>
35
36
#
include
<
QtUiPlugin
/
customwidget
.
h
>
37
38
#
include
<
QtWidgets
/
QtWidgets
>
39
#
include
<
QtWidgets
/
qscrollbar
.
h
>
40
#
include
<
QtWidgets
/
qfontcombobox
.
h
>
41
#
include
<
QtWidgets
/
qabstractspinbox
.
h
>
42
#
include
<
QtWidgets
/
qlineedit
.
h
>
43
#
include
<
QtWidgets
/
qbuttongroup
.
h
>
44
#
include
<
QtWidgets
/
qstyle
.
h
>
45
#
include
<
QtWidgets
/
qstylefactory
.
h
>
46
#
include
<
QtWidgets
/
qwizard
.
h
>
47
#
include
<
QtCore
/
qdebug
.
h
>
48
#
include
<
QtCore
/
qmetaobject
.
h
>
49
#
include
<
QtCore
/
qpointer
.
h
>
50
51
#
if
QT_CONFIG
(
abstractbutton
)
52
#
include
<
QtWidgets
/
qabstractbutton
.
h
>
53
#
endif
54
55
#
if
QT_CONFIG
(
itemviews
)
56
#
include
<
QtWidgets
/
qabstractitemview
.
h
>
57
#
endif
58
59
#
ifdef
QT_OPENGLWIDGETS_LIB
60
#
include
<
QtOpenGLWidgets
/
qopenglwidget
.
h
>
61
#
endif
62
63
QT_BEGIN_NAMESPACE
64
65
using
namespace
Qt::StringLiterals;
66
67
#
ifdef
Q_OS_WIN
68
static
inline
bool
isAxWidget(
const
QObject *o)
69
{
70
// Is it one of QDesignerAxWidget/QDesignerAxPluginWidget?
71
static
const
char
axWidgetName[] =
"QDesignerAx"
;
72
static
const
size_t axWidgetNameLen = qstrlen(axWidgetName);
73
return
qstrncmp(o->metaObject()->className(), axWidgetName, axWidgetNameLen) == 0;
74
}
75
#
endif
76
77
/* Dynamic boolean property indicating object was created by the factory
78
* for the form editor. */
79
80
static
const
char
formEditorDynamicProperty
[] =
"_q_formEditorObject"
;
81
82
namespace
qdesigner_internal
{
83
84
#
if
QT_CONFIG
(
abstractbutton
)
85
86
class
QDesignerAbstractButton
:
public
QAbstractButton
87
{
88
public
:
89
using
QAbstractButton
::
QAbstractButton
;
90
91
protected
:
92
void
paintEvent
(
QPaintEvent
*)
override
{}
93
};
94
95
#
endif
96
97
#
if
QT_CONFIG
(
itemviews
)
98
99
class
QDesignerAbstractItemView
:
public
QAbstractItemView
100
{
101
public
:
102
using
QAbstractItemView
::
QAbstractItemView
;
103
104
QRect
visualRect
(
const
QModelIndex
&)
const
override
105
{
106
return
QRect
(
QPoint
(),
QSize
(10, 10));
107
}
108
109
void
scrollTo
(
const
QModelIndex
&,
ScrollHint
=
EnsureVisible
)
override
{}
110
111
QModelIndex
indexAt
(
const
QPoint
&)
const
override
112
{
113
return
{};
114
}
115
116
protected
:
117
QModelIndex
moveCursor
(
CursorAction
,
Qt
::
KeyboardModifiers
)
override
118
{
119
return
{};
120
}
121
122
int
horizontalOffset
()
const
override
{
return
0; }
123
int
verticalOffset
()
const
override
{
return
0; }
124
125
bool
isIndexHidden
(
const
QModelIndex
&)
const
override
{
return
false
; }
126
127
void
setSelection
(
const
QRect
&,
QItemSelectionModel
::
SelectionFlags
)
override
{}
128
129
QRegion
visualRegionForSelection
(
const
QItemSelection
&)
const
override
130
{
131
return
QRegion
(
QRect
(
QPoint
(),
QSize
(10, 10)));
132
}
133
};
134
135
#
endif
// QT_CONFIG(itemviews)
136
137
// A friendly SpinBox that grants access to its QLineEdit
138
class
FriendlySpinBox
:
public
QAbstractSpinBox
{
139
public
:
140
friend
class
WidgetFactory;
141
};
142
143
// An event filter for form-combo boxes that prevents the embedded line edit
144
// from getting edit focus (and drawing blue artifacts/lines). It catches the
145
// ChildPolished event when the "editable" property flips to true and the
146
// QLineEdit is created and turns off the LineEdit's focus policy.
147
148
class
ComboEventFilter
:
public
QObject
{
149
public
:
150
explicit
ComboEventFilter
(QComboBox *parent) :
QObject
(
parent
) {}
151
bool
eventFilter
(QObject *watched, QEvent *event)
override
;
152
};
153
154
bool
ComboEventFilter
::
eventFilter
(QObject *watched, QEvent *event)
155
{
156
if
(event->type() == QEvent::ChildPolished) {
157
QComboBox *cb =
static_cast
<QComboBox*>(watched);
158
if
(QLineEdit *le = cb->lineEdit()) {
159
le->setFocusPolicy(Qt::NoFocus);
160
le->setCursor(Qt::ArrowCursor);
161
}
162
}
163
return
QObject::eventFilter(watched, event);
164
}
165
166
/* Watch out for QWizards changing their pages and make sure that not some
167
* selected widget becomes invisible on a hidden page (causing the selection
168
* handles to shine through). Select the wizard in that case in analogy to
169
* the QTabWidget event filters, etc. */
170
171
class
WizardPageChangeWatcher
:
public
QObject
{
172
Q_OBJECT
173
public
:
174
explicit
WizardPageChangeWatcher
(
QWizard
*
parent
);
175
176
public
slots
:
177
void
pageChanged
();
178
};
179
180
WizardPageChangeWatcher
::WizardPageChangeWatcher(QWizard *parent) :
181
QObject(parent)
182
{
183
connect(parent, &QWizard::currentIdChanged,
this
, &WizardPageChangeWatcher::pageChanged);
184
}
185
186
void
WizardPageChangeWatcher
::pageChanged()
187
{
188
/* Use a bit more conservative approach than that for the QTabWidget,
189
* change the selection only if a selected child becomes invisible by
190
* changing the page. */
191
QWizard *wizard =
static_cast
<QWizard *>(parent());
192
QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(wizard);
193
if
(!fw)
194
return
;
195
QDesignerFormWindowCursorInterface *cursor = fw->cursor();
196
const
int
selCount = cursor->selectedWidgetCount();
197
for
(
int
i = 0; i < selCount; i++) {
198
if
(!cursor->selectedWidget(i)->isVisible()) {
199
fw->clearSelection(
false
);
200
fw->selectWidget(wizard,
true
);
201
break
;
202
}
203
}
204
}
205
206
// ---------------- WidgetFactory
207
const
char
*
WidgetFactory
::
disableStyleCustomPaintingPropertyC
=
"_q_custom_style_disabled"
;
208
209
WidgetFactory
::
WidgetFactory
(
QDesignerFormEditorInterface
*
core
,
QObject
*
parent
)
210
:
QDesignerWidgetFactoryInterface
(
parent
),
211
m_core
(
core
),
212
m_formWindow
(
nullptr
),
213
m_currentStyle
(
nullptr
)
214
{
215
}
216
217
WidgetFactory
::~
WidgetFactory
() =
default
;
218
219
QDesignerFormWindowInterface
*
WidgetFactory
::
currentFormWindow
(
QDesignerFormWindowInterface
*
fw
)
220
{
221
QDesignerFormWindowInterface
*
was
=
m_formWindow
;
222
m_formWindow
=
fw
;
223
return
was
;
224
}
225
226
void
WidgetFactory
::
loadPlugins
()
227
{
228
m_customFactory
.
clear
();
229
230
const
auto
&
lst
=
m_core
->
pluginManager
()->
registeredCustomWidgets
();
231
for
(
QDesignerCustomWidgetInterface
*
c
:
lst
)
232
m_customFactory
.
insert
(
c
->
name
(),
c
);
233
}
234
235
// Convencience to create non-widget objects. Returns 0 if unknown
236
QObject
*
WidgetFactory
::
createObject
(
const
QString
&
className
,
QObject
*
parent
)
const
237
{
238
if
(
className
.
isEmpty
()) {
239
qWarning
(
"** WARNING %s called with an empty class name"
,
Q_FUNC_INFO
);
240
return
nullptr
;
241
}
242
if
(
className
==
"QAction"_L1
)
243
return
new
QAction
(
parent
);
244
if
(
className
==
"QButtonGroup"_L1
)
245
return
new
QButtonGroup
(
parent
);
246
return
nullptr
;
247
}
248
249
// Check for mismatched class names in plugins, which is hard to track.
250
static
bool
classNameMatches
(
const
QObject *created,
const
QString &className)
251
{
252
#
ifdef
Q_OS_WIN
253
// Perform literal comparison first for QAxWidget, for which a meta object hack is in effect.
254
if
(isAxWidget(created))
255
return
true
;
256
#
endif
257
const
char
*createdClassNameC = created->metaObject()->className();
258
const
QByteArray classNameB = className.toUtf8();
259
const
char
*classNameC = classNameB.constData();
260
if
(qstrcmp(createdClassNameC, classNameC) == 0 || created->inherits(classNameC))
261
return
true
;
262
// QTBUG-53984: QWebEngineView property dummy
263
if
(classNameB ==
"QWebEngineView"
&& qstrcmp(createdClassNameC,
"fake::QWebEngineView"
) == 0)
264
return
true
;
265
return
false
;
266
}
267
268
QWidget
*
WidgetFactory
::
createCustomWidget
(
const
QString
&
className
,
QWidget
*
parentWidget
,
bool
*
creationError
)
const
269
{
270
*
creationError
=
false
;
271
272
auto
*
factory
=
m_customFactory
.
value
(
className
,
nullptr
);
273
if
(
factory
==
nullptr
)
274
return
nullptr
;
275
276
QWidget
*
rc
=
factory
->
createWidget
(
parentWidget
);
277
// shouldn't happen
278
if
(!
rc
) {
279
*
creationError
=
true
;
280
designerWarning
(
tr
(
"The custom widget factory registered for widgets of class %1 returned 0."
).
arg
(
className
));
281
return
nullptr
;
282
}
283
// Figure out the base class unless it is known
284
static
QSet
<
QString
>
knownCustomClasses
;
285
if
(!
knownCustomClasses
.
contains
(
className
)) {
286
QDesignerWidgetDataBaseInterface
*
wdb
=
m_core
->
widgetDataBase
();
287
const
int
widgetInfoIndex
=
wdb
->
indexOfObject
(
rc
,
false
);
288
if
(
widgetInfoIndex
!= -1) {
289
if
(
wdb
->
item
(
widgetInfoIndex
)->
extends
().
isEmpty
()) {
290
const
QDesignerMetaObjectInterface
*
mo
=
core
()->
introspection
()->
metaObject
(
rc
)->
superClass
();
291
// If we hit on a 'Q3DesignerXXWidget' that claims to be a 'Q3XXWidget', step
292
// over.
293
if
(
mo
&&
mo
->
className
() ==
className
)
294
mo
=
mo
->
superClass
();
295
while
(
mo
!=
nullptr
) {
296
if
(
core
()->
widgetDataBase
()->
indexOfClassName
(
mo
->
className
()) != -1) {
297
wdb
->
item
(
widgetInfoIndex
)->
setExtends
(
mo
->
className
());
298
break
;
299
}
300
mo
=
mo
->
superClass
();
301
}
302
}
303
knownCustomClasses
.
insert
(
className
);
304
}
305
}
306
// Since a language plugin may lie about its names, like Qt Jambi
307
// does, return immediately here...
308
QDesignerLanguageExtension
*
lang
=
309
qt_extension
<
QDesignerLanguageExtension
*>(
m_core
->
extensionManager
(),
m_core
);
310
if
(
lang
)
311
return
rc
;
312
313
// Check for mismatched class names which is hard to track.
314
if
(!
classNameMatches
(
rc
,
className
)) {
315
designerWarning
(
tr
(
"A class name mismatch occurred when creating a widget using the custom widget factory registered for widgets of class %1."
316
" It returned a widget of class %2."
)
317
.
arg
(
className
,
QString
::
fromUtf8
(
rc
->
metaObject
()->
className
())));
318
}
319
return
rc
;
320
}
321
322
323
QWidget
*
WidgetFactory
::
createWidget
(
const
QString
&
widgetName
,
QWidget
*
parentWidget
)
const
324
{
325
if
(
widgetName
.
isEmpty
()) {
326
qWarning
(
"** WARNING %s called with an empty class name"
,
Q_FUNC_INFO
);
327
return
nullptr
;
328
}
329
// Preview or for form window?
330
QDesignerFormWindowInterface
*
fw
=
m_formWindow
;
331
if
(!
fw
)
332
fw
=
QDesignerFormWindowInterface
::
findFormWindow
(
parentWidget
);
333
334
QWidget
*
w
=
nullptr
;
335
do
{
336
// 1) custom. If there is an explicit failure(factory wants to indicate something is wrong),
337
// return 0, do not try to find fallback, which might be worse in the case of Q3 widget.
338
bool
customWidgetCreationError
;
339
w
=
createCustomWidget
(
widgetName
,
parentWidget
, &
customWidgetCreationError
);
340
if
(
w
)
341
break
;
342
if
(
customWidgetCreationError
)
343
return
nullptr
;
344
345
// 2) Special widgets
346
if
(
widgetName
==
"Line"_L1
) {
347
w
=
new
Line
(
parentWidget
);
348
#
if
QT_CONFIG
(
abstractbutton
)
349
}
else
if
(
widgetName
== u"QAbstractButton") {
350
w
=
new
QDesignerAbstractButton
(
parentWidget
);
351
#
endif
352
#
if
QT_CONFIG
(
itemviews
)
353
}
else
if
(
widgetName
== u"QAbstractItemView") {
354
w
=
new
QDesignerAbstractItemView
(
parentWidget
);
355
#
endif
356
}
else
if
(
widgetName
==
"QDockWidget"_L1
) {
357
w
=
new
QDesignerDockWidget
(
parentWidget
);
358
}
else
if
(
widgetName
==
"QMenuBar"_L1
) {
359
w
=
new
QDesignerMenuBar
(
parentWidget
);
360
}
else
if
(
widgetName
==
"QMenu"_L1
) {
361
w
=
new
QDesignerMenu
(
parentWidget
);
362
}
else
if
(
widgetName
==
"Spacer"_L1
) {
363
w
=
new
Spacer
(
parentWidget
);
364
}
else
if
(
widgetName
==
"QLayoutWidget"_L1
) {
365
w
=
fw
?
new
QLayoutWidget
(
fw
,
parentWidget
) :
new
QWidget
(
parentWidget
);
366
}
else
if
(
widgetName
==
"QDialog"_L1
) {
367
if
(
fw
) {
368
w
=
new
QDesignerDialog
(
fw
,
parentWidget
);
369
}
else
{
370
w
=
new
QDialog
(
parentWidget
);
371
}
372
}
else
if
(
widgetName
==
"QWidget"_L1
) {
373
/* We want a 'QDesignerWidget' that draws a grid only for widget
374
* forms and container extension pages (not for preview and not
375
* for normal QWidget children on forms (legacy) */
376
if
(
fw
&&
parentWidget
) {
377
if
(
qt_extension
<
QDesignerContainerExtension
*>(
m_core
->
extensionManager
(),
parentWidget
)) {
378
w
=
new
QDesignerWidget
(
fw
,
parentWidget
);
379
}
else
{
380
if
(
parentWidget
==
fw
->
formContainer
())
381
w
=
new
QDesignerWidget
(
fw
,
parentWidget
);
382
}
383
}
384
if
(!
w
)
385
w
=
new
QWidget
(
parentWidget
);
386
}
387
if
(
w
)
388
break
;
389
390
// 3) table
391
QWidget
*
newWidget
=
createWidgetInstance
(
widgetName
,
parentWidget
);
392
if
(
newWidget
) {
393
Q_ASSERT
(
w
==
nullptr
);
394
w
=
newWidget
;
395
break
;
396
}
397
398
// 4) fallBack
399
const
QString
fallBackBaseClass
=
"QWidget"_L1
;
400
QDesignerWidgetDataBaseInterface
*
db
=
core
()->
widgetDataBase
();
401
QDesignerWidgetDataBaseItemInterface
*
item
=
db
->
item
(
db
->
indexOfClassName
(
widgetName
));
402
if
(
item
==
nullptr
) {
403
// Emergency: Create, derived from QWidget
404
QString
includeFile
=
widgetName
.
toLower
();
405
includeFile
+=
".h"_L1
;
406
item
=
appendDerived
(
db
,
widgetName
,
tr
(
"%1 Widget"
).
arg
(
widgetName
),
fallBackBaseClass
,
407
includeFile
,
true
,
true
);
408
Q_ASSERT
(
item
);
409
}
410
QString
baseClass
=
item
->
extends
();
411
if
(
baseClass
.
isEmpty
()) {
412
// Currently happens in the case of Q3-Support widgets
413
baseClass
=
fallBackBaseClass
;
414
}
415
if
(
QWidget
*
promotedWidget
=
createWidget
(
baseClass
,
parentWidget
)) {
416
promoteWidget
(
core
(),
promotedWidget
,
widgetName
);
417
return
promotedWidget
;
// Do not initialize twice.
418
}
419
}
while
(
false
);
420
421
Q_ASSERT
(
w
!=
nullptr
);
422
if
(
m_currentStyle
)
423
w
->
setStyle
(
m_currentStyle
);
424
initializeCommon
(
w
);
425
if
(
fw
) {
// form editor initialization
426
initialize
(
w
);
427
}
else
{
// preview-only initialization
428
initializePreview
(
w
);
429
}
430
return
w
;
431
}
432
433
QString
WidgetFactory
::
classNameOf
(
QDesignerFormEditorInterface
*
c
,
const
QObject
*
o
)
434
{
435
if
(
o
==
nullptr
)
436
return
QString
();
437
438
const
char
*
className
=
o
->
metaObject
()->
className
();
439
if
(!
o
->
isWidgetType
())
440
return
QLatin1StringView
(
className
);
441
const
QWidget
*
w
=
static_cast
<
const
QWidget
*>(
o
);
442
// check promoted before designer special
443
const
QString
customClassName
=
promotedCustomClassName
(
c
,
const_cast
<
QWidget
*>(
w
));
444
if
(!
customClassName
.
isEmpty
())
445
return
customClassName
;
446
if
(
qobject_cast
<
const
QDesignerMenuBar
*>(
w
))
447
return
u"QMenuBar"_s;
448
if
(
qobject_cast
<
const
QDesignerMenu
*>(
w
))
449
return
u"QMenu"_s;
450
if
(
qobject_cast
<
const
QDesignerDockWidget
*>(
w
))
451
return
u"QDockWidget"_s;
452
if
(
qobject_cast
<
const
QDesignerDialog
*>(
w
))
453
return
u"QDialog"_s;
454
if
(
qobject_cast
<
const
QDesignerWidget
*>(
w
))
455
return
u"QWidget"_s;
456
#
ifdef
Q_OS_WIN
457
if
(
isAxWidget
(
w
))
458
return
u"QAxWidget"_s;
459
#
endif
460
return
QLatin1StringView
(
className
);
461
}
462
463
QLayout
*
WidgetFactory
::
createUnmanagedLayout
(
QWidget
*
parentWidget
,
int
type
)
464
{
465
switch
(
type
) {
466
case
LayoutInfo
::
HBox
:
467
return
new
QHBoxLayout
(
parentWidget
);
468
case
LayoutInfo
::
VBox
:
469
return
new
QVBoxLayout
(
parentWidget
);
470
case
LayoutInfo
::
Grid
:
471
return
new
QGridLayout
(
parentWidget
);
472
case
LayoutInfo
::
Form
:
473
return
new
QFormLayout
(
parentWidget
);
474
default
:
475
Q_ASSERT
(0);
476
break
;
477
}
478
return
nullptr
;
479
}
480
481
482
/*!
483
\internal
484
Creates a layout on the widget \a widget of the type \a type
485
which can be \c HBox, \c VBox or \c Grid.
486
*/
487
488
QLayout
*
WidgetFactory
::
createLayout
(
QWidget
*
widget
,
QLayout
*
parentLayout
,
int
type
)
const
// ### (sizepolicy)
489
{
490
QDesignerMetaDataBaseInterface
*
metaDataBase
=
core
()->
metaDataBase
();
491
492
if
(
parentLayout
==
nullptr
) {
493
QWidget
*
page
=
containerOfWidget
(
widget
);
494
if
(
page
) {
495
widget
=
page
;
496
}
else
{
497
const
QString
msg
=
498
tr
(
"The current page of the container '%1' (%2) could not be determined while creating a layout."
499
"This indicates an inconsistency in the ui-file, probably a layout being constructed on a container widget."
)
500
.
arg
(
widget
->
objectName
(),
classNameOf
(
core
(),
widget
));
501
designerWarning
(
msg
);
502
}
503
}
504
505
Q_ASSERT
(
metaDataBase
->
item
(
widget
) !=
nullptr
);
// ensure the widget is managed
506
507
if
(
parentLayout
==
nullptr
&&
metaDataBase
->
item
(
widget
->
layout
()) ==
nullptr
) {
508
parentLayout
=
widget
->
layout
();
509
}
510
511
QWidget
*
parentWidget
=
parentLayout
!=
nullptr
?
nullptr
:
widget
;
512
513
QLayout
*
layout
=
createUnmanagedLayout
(
parentWidget
,
type
);
514
metaDataBase
->
add
(
layout
);
// add the layout in the MetaDataBase
515
516
QDesignerPropertySheetExtension
*
sheet
=
qt_extension
<
QDesignerPropertySheetExtension
*>(
core
()->
extensionManager
(),
layout
);
517
518
if
(
sheet
) {
519
sheet
->
setChanged
(
sheet
->
indexOf
(u"objectName"_s),
true
);
520
if
(
widget
->
inherits
(
"QLayoutWidget"
)) {
521
sheet
->
setProperty
(
sheet
->
indexOf
(u"leftMargin"_s), 0);
522
sheet
->
setProperty
(
sheet
->
indexOf
(u"topMargin"_s), 0);
523
sheet
->
setProperty
(
sheet
->
indexOf
(u"rightMargin"_s), 0);
524
sheet
->
setProperty
(
sheet
->
indexOf
(u"bottomMargin"_s), 0);
525
}
526
527
const
int
index
=
sheet
->
indexOf
(u"alignment"_s);
528
if
(
index
!= -1)
529
sheet
->
setChanged
(
index
,
true
);
530
}
531
532
if
(
metaDataBase
->
item
(
widget
->
layout
()) ==
nullptr
) {
533
Q_ASSERT
(
layout
->
parent
() ==
nullptr
);
534
QBoxLayout
*
box
=
qobject_cast
<
QBoxLayout
*>(
widget
->
layout
());
535
if
(!
box
) {
// we support only unmanaged box layouts
536
const
QString
msg
=
tr
(
"Attempt to add a layout to a widget '%1' (%2) which already has an unmanaged layout of type %3.\n"
537
"This indicates an inconsistency in the ui-file."
).
538
arg
(
widget
->
objectName
(),
classNameOf
(
core
(),
widget
),
classNameOf
(
core
(),
widget
->
layout
()));
539
designerWarning
(
msg
);
540
return
nullptr
;
541
}
542
box
->
addLayout
(
layout
);
543
}
544
545
return
layout
;
546
}
547
548
/*!
549
\internal
550
Returns the widget into which children should be inserted when \a
551
w is a container known to designer.
552
553
Usually, it is \a w itself, but there are exceptions (for example, a
554
tabwidget is known to designer as a container, but the child
555
widgets should be inserted into the current page of the
556
tabwidget. In this case, the current page of
557
the tabwidget would be returned.)
558
*/
559
QWidget
*
WidgetFactory
::
containerOfWidget
(
QWidget
*
w
)
const
560
{
561
if
(
QDesignerContainerExtension
*
container
=
qt_extension
<
QDesignerContainerExtension
*>(
core
()->
extensionManager
(),
w
))
562
return
container
->
widget
(
container
->
currentIndex
());
563
564
return
w
;
565
}
566
567
/*!
568
\internal
569
Returns the actual designer widget of the container \a w. This is
570
normally \a w itself, but it might be a parent or grand parent of \a w
571
(for example, when working with a tabwidget and \a w is the container which
572
contains and layouts children, but the actual widget known to
573
designer is the tabwidget which is the parent of \a w. In this case,
574
the tabwidget would be returned.)
575
*/
576
577
QWidget
*
WidgetFactory
::
widgetOfContainer
(
QWidget
*
w
)
const
578
{
579
// ### cleanup
580
if
(!
w
)
581
return
nullptr
;
582
if
(
w
->
parentWidget
() &&
w
->
parentWidget
()->
parentWidget
() &&
583
w
->
parentWidget
()->
parentWidget
()->
parentWidget
() &&
584
qobject_cast
<
QToolBox
*>(
w
->
parentWidget
()->
parentWidget
()->
parentWidget
()))
585
return
w
->
parentWidget
()->
parentWidget
()->
parentWidget
();
586
587
while
(
w
!=
nullptr
) {
588
if
(
core
()->
widgetDataBase
()->
isContainer
(
w
) ||
589
(
w
&&
qobject_cast
<
QDesignerFormWindowInterface
*>(
w
->
parentWidget
())))
590
return
w
;
591
592
w
=
w
->
parentWidget
();
593
}
594
595
return
w
;
596
}
597
598
QDesignerFormEditorInterface
*
WidgetFactory
::
core
()
const
599
{
600
return
m_core
;
601
}
602
603
// Necessary initializations for form editor/preview objects
604
void
WidgetFactory
::
initializeCommon
(
QWidget
*
widget
)
const
605
{
606
// Apply style
607
if
(
m_currentStyle
)
608
widget
->
setStyle
(
m_currentStyle
);
609
}
610
611
// Necessary initializations for preview objects
612
void
WidgetFactory
::
initializePreview
(
QWidget
*
widget
)
const
613
{
614
615
if
(
QStackedWidget
*
stackedWidget
=
qobject_cast
<
QStackedWidget
*>(
widget
)) {
616
QStackedWidgetPreviewEventFilter
::
install
(
stackedWidget
);
// Add browse button only.
617
return
;
618
}
619
}
620
621
// Necessary initializations for form editor objects
622
void
WidgetFactory
::
initialize
(
QObject
*
object
)
const
623
{
624
// Indicate that this is a form object (for QDesignerFormWindowInterface::findFormWindow)
625
object
->
setProperty
(
formEditorDynamicProperty
,
QVariant
(
true
));
626
QDesignerPropertySheetExtension
*
sheet
=
qt_extension
<
QDesignerPropertySheetExtension
*>(
m_core
->
extensionManager
(),
object
);
627
if
(!
sheet
)
628
return
;
629
630
sheet
->
setChanged
(
sheet
->
indexOf
(u"objectName"_s),
true
);
631
632
if
(!
object
->
isWidgetType
()) {
633
if
(
qobject_cast
<
QAction
*>(
object
))
634
sheet
->
setChanged
(
sheet
->
indexOf
(u"text"_s),
true
);
635
return
;
636
}
637
638
QWidget
*
widget
=
static_cast
<
QWidget
*>(
object
);
639
const
bool
isMenu
=
qobject_cast
<
QMenu
*>(
widget
);
640
const
bool
isMenuBar
= !
isMenu
&&
qobject_cast
<
QMenuBar
*>(
widget
);
641
642
widget
->
setAttribute
(
Qt
::
WA_TransparentForMouseEvents
,
false
);
643
widget
->
setFocusPolicy
((
isMenu
||
isMenuBar
) ?
Qt
::
StrongFocus
:
Qt
::
NoFocus
);
644
645
if
(!
isMenu
)
646
sheet
->
setChanged
(
sheet
->
indexOf
(u"geometry"_s),
true
);
647
648
if
(
qobject_cast
<
Spacer
*>(
widget
)) {
649
sheet
->
setChanged
(
sheet
->
indexOf
(u"spacerName"_s),
true
);
650
return
;
651
}
652
653
const
int
o
=
sheet
->
indexOf
(u"orientation"_s);
654
if
(
o
!= -1 &&
widget
->
inherits
(
"QSplitter"
))
655
sheet
->
setChanged
(
o
,
true
);
656
657
if
(
QToolBar
*
toolBar
=
qobject_cast
<
QToolBar
*>(
widget
)) {
658
ToolBarEventFilter
::
install
(
toolBar
);
659
sheet
->
setVisible
(
sheet
->
indexOf
(u"windowTitle"_s),
true
);
660
toolBar
->
setFloatable
(
false
);
// prevent toolbars from being dragged off
661
return
;
662
}
663
664
if
(
qobject_cast
<
QDockWidget
*>(
widget
)) {
665
sheet
->
setVisible
(
sheet
->
indexOf
(u"windowTitle"_s),
true
);
666
sheet
->
setVisible
(
sheet
->
indexOf
(u"windowIcon"_s),
true
);
667
return
;
668
}
669
670
if
(
isMenu
) {
671
sheet
->
setChanged
(
sheet
->
indexOf
(u"title"_s),
true
);
672
return
;
673
}
674
// helpers
675
if
(
QToolBox
*
toolBox
=
qobject_cast
<
QToolBox
*>(
widget
)) {
676
QToolBoxHelper
::
install
(
toolBox
);
677
return
;
678
}
679
if
(
QStackedWidget
*
stackedWidget
=
qobject_cast
<
QStackedWidget
*>(
widget
)) {
680
QStackedWidgetEventFilter
::
install
(
stackedWidget
);
681
return
;
682
}
683
if
(
QTabWidget
*
tabWidget
=
qobject_cast
<
QTabWidget
*>(
widget
)) {
684
QTabWidgetEventFilter
::
install
(
tabWidget
);
685
return
;
686
}
687
// Prevent embedded line edits from getting focus
688
if
(
QAbstractSpinBox
*
asb
=
qobject_cast
<
QAbstractSpinBox
*>(
widget
)) {
689
if
(
QLineEdit
*
lineEdit
=
static_cast
<
FriendlySpinBox
*>(
asb
)->
lineEdit
())
690
lineEdit
->
setFocusPolicy
(
Qt
::
NoFocus
);
691
return
;
692
}
693
if
(
QComboBox
*
cb
=
qobject_cast
<
QComboBox
*>(
widget
)) {
694
if
(
QFontComboBox
*
fcb
=
qobject_cast
<
QFontComboBox
*>(
widget
)) {
695
fcb
->
lineEdit
()->
setFocusPolicy
(
Qt
::
NoFocus
);
// Always present
696
return
;
697
}
698
cb
->
installEventFilter
(
new
ComboEventFilter
(
cb
));
699
return
;
700
}
701
if
(
QWizard
*
wz
=
qobject_cast
<
QWizard
*>(
widget
)) {
702
WizardPageChangeWatcher
*
pw
=
new
WizardPageChangeWatcher
(
wz
);
703
Q_UNUSED
(
pw
);
704
}
705
}
706
707
static
inline
QString
classNameOfStyle
(
const
QStyle *s)
708
{
709
return
QLatin1StringView(s->metaObject()->className());
710
}
711
712
QString
WidgetFactory
::
styleName
()
const
713
{
714
return
classNameOfStyle
(
style
());
715
}
716
717
static
inline
bool
isApplicationStyle
(
const
QString &styleName)
718
{
719
return
styleName.isEmpty() || styleName == classNameOfStyle(qApp->style());
720
}
721
722
void
WidgetFactory
::
setStyleName
(
const
QString
&
styleName
)
723
{
724
m_currentStyle
=
isApplicationStyle
(
styleName
) ?
nullptr
:
getStyle
(
styleName
);
725
}
726
727
QStyle
*
WidgetFactory
::
style
()
const
728
{
729
return
m_currentStyle
?
m_currentStyle
:
qApp
->
style
();
730
}
731
732
QStyle
*
WidgetFactory
::
getStyle
(
const
QString
&
styleName
)
733
{
734
if
(
isApplicationStyle
(
styleName
))
735
return
qApp
->
style
();
736
737
auto
it
=
m_styleCache
.
find
(
styleName
);
738
if
(
it
==
m_styleCache
.
end
()) {
739
QStyle
*
style
=
QStyleFactory
::
create
(
styleName
);
740
if
(!
style
) {
741
const
QString
msg
=
tr
(
"Cannot create style '%1'."
).
arg
(
styleName
);
742
designerWarning
(
msg
);
743
return
nullptr
;
744
}
745
it
=
m_styleCache
.
insert
(
styleName
,
style
);
746
}
747
return
it
.
value
();
748
}
749
750
void
WidgetFactory
::
applyStyleTopLevel
(
const
QString
&
styleName
,
QWidget
*
w
)
751
{
752
if
(
QStyle
*
style
=
getStyle
(
styleName
))
753
applyStyleToTopLevel
(
style
,
w
);
754
}
755
756
void
WidgetFactory
::
applyStyleToTopLevel
(
QStyle
*
style
,
QWidget
*
widget
)
757
{
758
if
(!
style
)
759
return
;
760
const
QPalette
standardPalette
=
style
->
standardPalette
();
761
if
(
widget
->
style
() ==
style
&&
widget
->
palette
() ==
standardPalette
)
762
return
;
763
764
widget
->
setStyle
(
style
);
765
widget
->
setPalette
(
standardPalette
);
766
const
QWidgetList
lst
=
widget
->
findChildren
<
QWidget
*>();
767
for
(
auto
*
w
:
lst
)
768
w
->
setStyle
(
style
);
769
}
770
771
// Check for 'interactor' click on a tab bar,
772
// which can appear within a QTabWidget or as a standalone widget.
773
774
static
bool
isTabBarInteractor
(
const
QTabBar *tabBar)
775
{
776
// Tabbar embedded in Q(Designer)TabWidget, ie, normal tab widget case
777
if
(qobject_cast<
const
QTabWidget*>(tabBar->parentWidget()))
778
return
true
;
779
780
// Standalone tab bar on the form. Return true for tab rect areas
781
// only to allow the user to select the tab bar by clicking outside the actual tabs.
782
const
int
count = tabBar->count();
783
if
(count == 0)
784
return
false
;
785
786
// click into current tab: No Interaction
787
const
int
currentIndex = tabBar->currentIndex();
788
const
QPoint pos = tabBar->mapFromGlobal(QCursor::pos());
789
if
(tabBar->tabRect(currentIndex).contains(pos))
790
return
false
;
791
792
// click outside: No Interaction
793
const
QRect geometry = QRect(QPoint(0, 0), tabBar->size());
794
if
(!geometry.contains(pos))
795
return
false
;
796
// click into another tab: Let's interact, switch tabs.
797
for
(
int
i = 0; i < count; i++)
798
if
(tabBar->tabRect(i).contains(pos))
799
return
true
;
800
return
false
;
801
}
802
803
static
bool
isPassiveInteractorHelper
(
const
QWidget
*widget)
804
{
805
if
(qobject_cast<
const
QMenuBar*>(widget)
806
#
if
QT_CONFIG
(
sizegrip
)
807
|| qobject_cast<
const
QSizeGrip*>(widget)
808
#
endif
809
|| qobject_cast<
const
QMdiSubWindow*>(widget)
810
|| qobject_cast<
const
QToolBar*>(widget)) {
811
return
true
;
812
}
813
814
if
(qobject_cast<
const
QAbstractButton*>(widget)) {
815
auto
parent = widget->parent();
816
if
(qobject_cast<
const
QTabBar*>(parent) || qobject_cast<
const
QToolBox*>(parent))
817
return
true
;
818
}
else
if
(
const
auto
tabBar = qobject_cast<
const
QTabBar*>(widget)) {
819
if
(isTabBarInteractor(tabBar))
820
return
true
;
821
}
else
if
(qobject_cast<
const
QScrollBar*>(widget)) {
822
// A scroll bar is an interactor on a QAbstractScrollArea only.
823
if
(
auto
parent = widget->parentWidget()) {
824
const
QString &objectName = parent->objectName();
825
if
(objectName ==
"qt_scrollarea_vcontainer"_L1
|| objectName ==
"qt_scrollarea_hcontainer"_L1
)
826
return
true
;
827
}
828
}
else
if
(qstrcmp(widget->metaObject()->className(),
"QDockWidgetTitle"
) == 0) {
829
return
true
;
830
}
else
if
(qstrcmp(widget->metaObject()->className(),
"QWorkspaceTitleBar"
) == 0) {
831
return
true
;
832
}
833
const
QString &name = widget->objectName();
834
return
name.startsWith(
"__qt__passive_"_L1
)
835
|| name ==
"qt_qmainwindow_extended_splitter"_L1
;
836
}
837
838
bool
WidgetFactory
::
isPassiveInteractor
(
QWidget
*
widget
)
839
{
840
static
bool
lastWasAPassiveInteractor
=
false
;
841
static
QPointer
<
QWidget
>
lastPassiveInteractor
;
842
843
if
(!
lastPassiveInteractor
.
isNull
() &&
lastPassiveInteractor
.
data
() ==
widget
)
844
return
lastWasAPassiveInteractor
;
845
846
// if a popup is open, we have to make sure that this one is closed,
847
// else X might do funny things
848
if
(
QApplication
::
activePopupWidget
() ||
widget
==
nullptr
)
849
return
true
;
850
851
lastWasAPassiveInteractor
=
isPassiveInteractorHelper
(
widget
);
852
lastPassiveInteractor
=
widget
;
853
854
return
lastWasAPassiveInteractor
;
855
}
856
857
void
WidgetFactory
::
formWindowAdded
(
QDesignerFormWindowInterface
*
formWindow
)
858
{
859
setFormWindowStyle
(
formWindow
);
860
}
861
862
void
WidgetFactory
::
activeFormWindowChanged
(
QDesignerFormWindowInterface
*
formWindow
)
863
{
864
setFormWindowStyle
(
formWindow
);
865
}
866
867
void
WidgetFactory
::
setFormWindowStyle
(
QDesignerFormWindowInterface
*
formWindow
)
868
{
869
if
(
FormWindowBase
*
fwb
=
qobject_cast
<
FormWindowBase
*>(
formWindow
))
870
setStyleName
(
fwb
->
styleName
());
871
}
872
873
bool
WidgetFactory
::
isFormEditorObject
(
const
QObject
*
object
)
874
{
875
return
object
->
property
(
formEditorDynamicProperty
).
isValid
();
876
}
877
}
// namespace qdesigner_internal
878
879
QT_END_NAMESPACE
880
881
#
include
"widgetfactory.moc"
QPainter::QWidget
friend class QWidget
Definition
qpainter.h:432
qdesigner_internal::ComboEventFilter
Definition
widgetfactory.cpp:148
qdesigner_internal::ComboEventFilter::eventFilter
bool eventFilter(QObject *watched, QEvent *event) override
Filters events if this object has been installed as an event filter for the watched object.
Definition
widgetfactory.cpp:154
qdesigner_internal::ComboEventFilter::ComboEventFilter
ComboEventFilter(QComboBox *parent)
Definition
widgetfactory.cpp:150
qdesigner_internal::FriendlySpinBox
Definition
widgetfactory.cpp:138
qdesigner_internal::WizardPageChangeWatcher
Definition
widgetfactory.cpp:171
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qdesigner_internal
Auxiliary methods to store/retrieve settings.
Definition
buddyeditor.cpp:67
qdesigner_internal::isPassiveInteractorHelper
static bool isPassiveInteractorHelper(const QWidget *widget)
Definition
widgetfactory.cpp:803
qdesigner_internal::isTabBarInteractor
static bool isTabBarInteractor(const QTabBar *tabBar)
Definition
widgetfactory.cpp:774
qdesigner_internal::classNameOfStyle
static QString classNameOfStyle(const QStyle *s)
Definition
widgetfactory.cpp:707
qdesigner_internal::classNameMatches
static bool classNameMatches(const QObject *created, const QString &className)
Definition
widgetfactory.cpp:250
qdesigner_internal::isApplicationStyle
static bool isApplicationStyle(const QString &styleName)
Definition
widgetfactory.cpp:717
formEditorDynamicProperty
static const char formEditorDynamicProperty[]
Definition
widgetfactory.cpp:80
qttools
src
designer
src
lib
shared
widgetfactory.cpp
Generated on
for Qt by
1.18.0