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
actioneditor.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
"actioneditor_p.h"
6
#
include
"actionrepository_p.h"
7
#
include
"iconloader_p.h"
8
#
include
"newactiondialog_p.h"
9
#
include
"qdesigner_menu_p.h"
10
#
include
"qdesigner_command_p.h"
11
#
include
"qdesigner_propertycommand_p.h"
12
#
include
"qdesigner_objectinspector_p.h"
13
#
include
"qdesigner_utils_p.h"
14
#
include
"qsimpleresource_p.h"
15
#
include
"formwindowbase_p.h"
16
#
include
"qdesigner_taskmenu_p.h"
17
18
#
include
<
QtDesigner
/
abstractformeditor
.
h
>
19
#
include
<
QtDesigner
/
abstractpropertyeditor
.
h
>
20
#
include
<
QtDesigner
/
propertysheet
.
h
>
21
#
include
<
QtDesigner
/
qextensionmanager
.
h
>
22
#
include
<
QtDesigner
/
abstractmetadatabase
.
h
>
23
#
include
<
QtDesigner
/
abstractsettings
.
h
>
24
25
#
include
<
QtWidgets
/
qmenu
.
h
>
26
#
include
<
QtWidgets
/
qtoolbar
.
h
>
27
#
include
<
QtWidgets
/
qsplitter
.
h
>
28
#
include
<
QtWidgets
/
qapplication
.
h
>
29
#
if
QT_CONFIG
(
clipboard
)
30
#
include
<
QtGui
/
qclipboard
.
h
>
31
#
endif
32
#
include
<
QtWidgets
/
qitemdelegate
.
h
>
33
#
include
<
QtWidgets
/
qboxlayout
.
h
>
34
#
include
<
QtWidgets
/
qlineedit
.
h
>
35
#
include
<
QtWidgets
/
qlabel
.
h
>
36
#
include
<
QtWidgets
/
qpushbutton
.
h
>
37
#
include
<
QtWidgets
/
qtoolbutton
.
h
>
38
39
#
include
<
QtGui
/
qaction
.
h
>
40
#
include
<
QtGui
/
qactiongroup
.
h
>
41
#
include
<
QtGui
/
qevent
.
h
>
42
#
include
<
QtGui
/
qpainter
.
h
>
43
44
#
include
<
QtCore
/
qitemselectionmodel
.
h
>
45
#
include
<
QtCore
/
qregularexpression
.
h
>
46
#
include
<
QtCore
/
qdebug
.
h
>
47
#
include
<
QtCore
/
qbuffer
.
h
>
48
49
QT_BEGIN_NAMESPACE
50
51
using
namespace
Qt::StringLiterals;
52
53
static
constexpr
auto
actionEditorViewModeKey
=
"ActionEditorViewMode"_L1
;
54
55
static
constexpr
auto
iconPropertyC
=
"icon"_L1
;
56
static
constexpr
auto
shortcutPropertyC
=
"shortcut"_L1
;
57
static
constexpr
auto
menuRolePropertyC
=
"menuRole"_L1
;
58
static
constexpr
auto
toolTipPropertyC
=
"toolTip"_L1
;
59
static
constexpr
auto
checkablePropertyC
=
"checkable"_L1
;
60
static
constexpr
auto
objectNamePropertyC
=
"objectName"_L1
;
61
static
constexpr
auto
textPropertyC
=
"text"_L1
;
62
63
namespace
qdesigner_internal
{
64
//-------- ActionGroupDelegate
65
class
ActionGroupDelegate
:
public
QItemDelegate
66
{
67
public
:
68
ActionGroupDelegate
(QObject *parent)
69
:
QItemDelegate
(
parent
) {}
70
71
void
paint
(
QPainter
*painter,
const
QStyleOptionViewItem &option,
const
QModelIndex &index)
const
override
72
{
73
if
(option.state & QStyle::State_Selected)
74
painter->fillRect(option.rect, option.palette.highlight());
75
76
QItemDelegate::paint(painter, option, index);
77
}
78
79
void
drawFocus
(
QPainter
*,
const
QStyleOptionViewItem &,
const
QRect &)
const
override
{}
80
};
81
82
//-------- ActionEditor
83
ObjectNamingMode
ActionEditor
::
m_objectNamingMode
=
CamelCase
;
84
85
ActionEditor
::
ActionEditor
(
QDesignerFormEditorInterface
*
core
,
QWidget
*
parent
,
Qt
::
WindowFlags
flags
) :
86
QDesignerActionEditorInterface
(
parent
,
flags
),
87
m_core
(
core
),
88
m_actionGroups
(
nullptr
),
89
m_actionView
(
new
ActionView
),
90
m_actionNew
(
new
QAction
(
tr
(
"New..."
),
this
)),
91
m_actionEdit
(
new
QAction
(
tr
(
"Edit..."
),
this
)),
92
m_actionNavigateToSlot
(
new
QAction
(
tr
(
"Go to slot..."
),
this
)),
93
#
if
QT_CONFIG
(
clipboard
)
94
m_actionCopy
(
new
QAction
(
tr
(
"Copy"
),
this
)),
95
m_actionCut
(
new
QAction
(
tr
(
"Cut"
),
this
)),
96
m_actionPaste
(
new
QAction
(
tr
(
"Paste"
),
this
)),
97
#
endif
98
m_actionSelectAll
(
new
QAction
(
tr
(
"Select all"
),
this
)),
99
m_actionDelete
(
new
QAction
(
tr
(
"Delete"
),
this
)),
100
m_viewModeGroup
(
new
QActionGroup
(
this
)),
101
m_iconViewAction
(
nullptr
),
102
m_listViewAction
(
nullptr
),
103
m_filterWidget
(
nullptr
)
104
{
105
m_actionView
->
initialize
(
m_core
);
106
m_actionView
->
setSelectionMode
(
QAbstractItemView
::
ExtendedSelection
);
107
setWindowTitle
(
tr
(
"Actions"
));
108
109
QVBoxLayout
*
l
=
new
QVBoxLayout
(
this
);
110
l
->
setContentsMargins
(
QMargins
());
111
l
->
setSpacing
(0);
112
113
QToolBar
*
toolbar
=
new
QToolBar
;
114
toolbar
->
setIconSize
(
QSize
(22, 22));
115
toolbar
->
setSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Minimum
);
116
l
->
addWidget
(
toolbar
);
117
// edit actions
118
QIcon
documentNewIcon
=
createIconSet
(
QIcon
::
ThemeIcon
::
DocumentNew
,
119
"filenew.png"_L1
);
120
m_actionNew
->
setIcon
(
documentNewIcon
);
121
m_actionNew
->
setEnabled
(
false
);
122
connect
(
m_actionNew
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
slotNewAction
);
123
toolbar
->
addAction
(
m_actionNew
);
124
125
connect
(
m_actionSelectAll
, &
QAction
::
triggered
,
m_actionView
, &
ActionView
::
selectAll
);
126
127
#
if
QT_CONFIG
(
clipboard
)
128
m_actionCut
->
setEnabled
(
false
);
129
connect
(
m_actionCut
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
slotCut
);
130
QIcon
editCutIcon
=
createIconSet
(
QIcon
::
ThemeIcon
::
EditCut
,
131
"editcut.png"_L1
);
132
m_actionCut
->
setIcon
(
editCutIcon
);
133
134
m_actionCopy
->
setEnabled
(
false
);
135
connect
(
m_actionCopy
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
slotCopy
);
136
QIcon
editCopyIcon
=
createIconSet
(
QIcon
::
ThemeIcon
::
EditCopy
,
137
"editcopy.png"_L1
);
138
m_actionCopy
->
setIcon
(
editCopyIcon
);
139
toolbar
->
addAction
(
m_actionCopy
);
140
141
connect
(
m_actionPaste
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
slotPaste
);
142
QIcon
editPasteIcon
=
createIconSet
(
QIcon
::
ThemeIcon
::
EditPaste
,
143
"editpaste.png"_L1
);
144
m_actionPaste
->
setIcon
(
editPasteIcon
);
145
toolbar
->
addAction
(
m_actionPaste
);
146
#
endif
147
148
m_actionEdit
->
setEnabled
(
false
);
149
connect
(
m_actionEdit
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
editCurrentAction
);
150
151
connect
(
m_actionNavigateToSlot
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
navigateToSlotCurrentAction
);
152
153
QIcon
editDeleteIcon
=
createIconSet
(
QIcon
::
ThemeIcon
::
EditDelete
,
154
"editdelete.png"_L1
);
155
m_actionDelete
->
setIcon
(
editDeleteIcon
);
156
m_actionDelete
->
setEnabled
(
false
);
157
connect
(
m_actionDelete
, &
QAction
::
triggered
,
this
, &
ActionEditor
::
slotDelete
);
158
toolbar
->
addAction
(
m_actionDelete
);
159
160
// Toolbutton with menu containing action group for detailed/icon view. Steal the icons from the file dialog.
161
//
162
QMenu
*
configureMenu
;
163
toolbar
->
addWidget
(
createConfigureMenuButton
(
tr
(
"Configure Action Editor"
), &
configureMenu
));
164
165
connect
(
m_viewModeGroup
, &
QActionGroup
::
triggered
,
this
, &
ActionEditor
::
slotViewMode
);
166
m_iconViewAction
=
m_viewModeGroup
->
addAction
(
tr
(
"Icon View"
));
167
m_iconViewAction
->
setData
(
QVariant
(
ActionView
::
IconView
));
168
m_iconViewAction
->
setCheckable
(
true
);
169
m_iconViewAction
->
setIcon
(
style
()->
standardIcon
(
QStyle
::
SP_FileDialogListView
));
170
configureMenu
->
addAction
(
m_iconViewAction
);
171
172
m_listViewAction
=
m_viewModeGroup
->
addAction
(
tr
(
"Detailed View"
));
173
m_listViewAction
->
setData
(
QVariant
(
ActionView
::
DetailedView
));
174
m_listViewAction
->
setCheckable
(
true
);
175
m_listViewAction
->
setIcon
(
style
()->
standardIcon
(
QStyle
::
SP_FileDialogDetailedView
));
176
configureMenu
->
addAction
(
m_listViewAction
);
177
// filter
178
m_filterWidget
=
new
QWidget
(
toolbar
);
179
QHBoxLayout
*
filterLayout
=
new
QHBoxLayout
(
m_filterWidget
);
180
filterLayout
->
setContentsMargins
(0, 0, 0, 0);
181
QLineEdit
*
filterLineEdit
=
new
QLineEdit
(
m_filterWidget
);
182
connect
(
filterLineEdit
, &
QLineEdit
::
textChanged
,
this
, &
ActionEditor
::
setFilter
);
183
filterLineEdit
->
setPlaceholderText
(
tr
(
"Filter"
));
184
filterLineEdit
->
setClearButtonEnabled
(
true
);
185
filterLayout
->
addItem
(
new
QSpacerItem
(0, 0,
QSizePolicy
::
MinimumExpanding
,
QSizePolicy
::
Ignored
));
186
filterLayout
->
addWidget
(
filterLineEdit
);
187
m_filterWidget
->
setEnabled
(
false
);
188
toolbar
->
addWidget
(
m_filterWidget
);
189
190
// main layout
191
QSplitter
*
splitter
=
new
QSplitter
(
Qt
::
Horizontal
);
192
splitter
->
setSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Expanding
);
193
194
splitter
->
addWidget
(
m_actionView
);
195
l
->
addWidget
(
splitter
);
196
197
#
if
0
// ### implement me
198
m_actionGroups
=
new
QListWidget
(
splitter
);
199
splitter
->
addWidget
(
m_actionGroups
);
200
m_actionGroups
->
setItemDelegate
(
new
ActionGroupDelegate
(
m_actionGroups
));
201
m_actionGroups
->
setMovement
(
QListWidget
::
Static
);
202
m_actionGroups
->
setResizeMode
(
QListWidget
::
Fixed
);
203
m_actionGroups
->
setIconSize
(
QSize
(48, 48));
204
m_actionGroups
->
setFlow
(
QListWidget
::
TopToBottom
);
205
m_actionGroups
->
setViewMode
(
QListWidget
::
IconMode
);
206
m_actionGroups
->
setWrapping
(
false
);
207
#
endif
208
209
connect
(
m_actionView
, &
ActionView
::
resourceImageDropped
,
210
this
, &
ActionEditor
::
resourceImageDropped
);
211
212
connect
(
m_actionView
, &
ActionView
::
currentActionChanged
,
213
this
, &
ActionEditor
::
slotCurrentItemChanged
);
214
// make it possible for vs integration to reimplement edit action dialog
215
connect
(
m_actionView
, &
ActionView
::
activated
,
this
, &
ActionEditor
::
itemActivated
);
216
217
connect
(
m_actionView
, &
ActionView
::
selectionChanged
,
218
this
, &
ActionEditor
::
slotSelectionChanged
);
219
220
connect
(
m_actionView
, &
ActionView
::
contextMenuRequested
,
221
this
, &
ActionEditor
::
slotContextMenuRequested
);
222
223
connect
(
this
, &
ActionEditor
::
itemActivated
,
this
, &
ActionEditor
::
editAction
);
224
225
restoreSettings
();
226
updateViewModeActions
();
227
}
228
229
// Utility to create a configure button with menu for usage on toolbars
230
QToolButton
*
ActionEditor
::
createConfigureMenuButton
(
const
QString
&
t
,
QMenu
**
ptrToMenu
)
231
{
232
QToolButton
*
configureButton
=
new
QToolButton
;
233
QAction
*
configureAction
=
new
QAction
(
t
,
configureButton
);
234
QIcon
configureIcon
=
QIcon
::
fromTheme
(
QIcon
::
ThemeIcon
::
DocumentProperties
,
235
createIconSet
(
"configure.png"_L1
));
236
configureAction
->
setIcon
(
configureIcon
);
237
QMenu
*
configureMenu
=
new
QMenu
(
configureButton
);
238
configureAction
->
setMenu
(
configureMenu
);
239
configureButton
->
setDefaultAction
(
configureAction
);
240
configureButton
->
setPopupMode
(
QToolButton
::
InstantPopup
);
241
*
ptrToMenu
=
configureMenu
;
242
return
configureButton
;
243
}
244
245
ActionEditor
::~
ActionEditor
()
246
{
247
saveSettings
();
248
}
249
250
QAction
*
ActionEditor
::
actionNew
()
const
251
{
252
return
m_actionNew
;
253
}
254
255
QAction
*
ActionEditor
::
actionDelete
()
const
256
{
257
return
m_actionDelete
;
258
}
259
260
QDesignerFormWindowInterface
*
ActionEditor
::
formWindow
()
const
261
{
262
return
m_formWindow
;
263
}
264
265
void
ActionEditor
::
setFormWindow
(
QDesignerFormWindowInterface
*
formWindow
)
266
{
267
if
(
formWindow
!=
nullptr
&&
formWindow
->
mainContainer
() ==
nullptr
)
268
formWindow
=
nullptr
;
269
270
// we do NOT rely on this function to update the action editor
271
if
(
m_formWindow
==
formWindow
)
272
return
;
273
274
if
(
m_formWindow
!=
nullptr
) {
275
const
ActionList
actionList
=
m_formWindow
->
mainContainer
()->
findChildren
<
QAction
*>();
276
for
(
QAction
*
action
:
actionList
)
277
disconnect
(
action
, &
QAction
::
changed
,
this
, &
ActionEditor
::
slotActionChanged
);
278
}
279
280
m_formWindow
=
formWindow
;
281
282
m_actionView
->
model
()->
clearActions
();
283
284
m_actionEdit
->
setEnabled
(
false
);
285
#
if
QT_CONFIG
(
clipboard
)
286
m_actionCopy
->
setEnabled
(
false
);
287
m_actionCut
->
setEnabled
(
false
);
288
#
endif
289
m_actionDelete
->
setEnabled
(
false
);
290
291
if
(!
formWindow
|| !
formWindow
->
mainContainer
()) {
292
m_actionNew
->
setEnabled
(
false
);
293
m_filterWidget
->
setEnabled
(
false
);
294
return
;
295
}
296
297
m_actionNew
->
setEnabled
(
true
);
298
m_filterWidget
->
setEnabled
(
true
);
299
300
const
ActionList
actionList
=
formWindow
->
mainContainer
()->
findChildren
<
QAction
*>();
301
for
(
QAction
*
action
:
actionList
)
302
if
(!
action
->
isSeparator
() &&
core
()->
metaDataBase
()->
item
(
action
) !=
nullptr
) {
303
// Show unless it has a menu. However, listen for change on menu actions also as it might be removed
304
if
(!
action
->
menu
())
305
m_actionView
->
model
()->
addAction
(
action
);
306
connect
(
action
, &
QAction
::
changed
,
this
, &
ActionEditor
::
slotActionChanged
);
307
}
308
309
setFilter
(
m_filter
);
310
}
311
312
void
ActionEditor
::
slotSelectionChanged
(
const
QItemSelection
&
selected
,
const
QItemSelection
&
/*deselected*/
)
313
{
314
const
bool
hasSelection
= !
selected
.
indexes
().
isEmpty
();
315
#
if
QT_CONFIG
(
clipboard
)
316
m_actionCopy
->
setEnabled
(
hasSelection
);
317
m_actionCut
->
setEnabled
(
hasSelection
);
318
#
endif
319
m_actionDelete
->
setEnabled
(
hasSelection
);
320
}
321
322
void
ActionEditor
::
slotCurrentItemChanged
(
QAction
*
action
)
323
{
324
QDesignerFormWindowInterface
*
fw
=
formWindow
();
325
if
(
m_withinSelectAction
||
fw
==
nullptr
)
326
return
;
327
328
const
bool
hasCurrentAction
=
action
!=
nullptr
;
329
m_actionEdit
->
setEnabled
(
hasCurrentAction
);
330
331
if
(!
action
) {
332
fw
->
clearSelection
();
333
return
;
334
}
335
336
QDesignerObjectInspector
*
oi
=
qobject_cast
<
QDesignerObjectInspector
*>(
core
()->
objectInspector
());
337
338
// Check if we have at least one associated QWidget:
339
const
auto
associatedObjects
=
action
->
associatedObjects
();
340
auto
it
=
std
::
find_if
(
associatedObjects
.
cbegin
(),
associatedObjects
.
cend
(),
341
[](
QObject
*
obj
) {
342
return
qobject_cast
<
QWidget
*>(
obj
) !=
nullptr
;
343
});
344
if
(
it
==
associatedObjects
.
cend
()) {
345
// Special case: action not in object tree. Deselect all and set in property editor
346
fw
->
clearSelection
(
false
);
347
if
(
oi
)
348
oi
->
clearSelection
();
349
core
()->
propertyEditor
()->
setObject
(
action
);
350
}
else
{
351
if
(
oi
)
352
oi
->
selectObject
(
action
);
353
}
354
}
355
356
void
ActionEditor
::
slotActionChanged
()
357
{
358
QAction
*
action
=
qobject_cast
<
QAction
*>(
sender
());
359
Q_ASSERT
(
action
!=
nullptr
);
360
361
ActionModel
*
model
=
m_actionView
->
model
();
362
const
int
row
=
model
->
findAction
(
action
);
363
if
(
row
== -1) {
364
if
(
action
->
menu
() ==
nullptr
)
// action got its menu deleted, create item
365
model
->
addAction
(
action
);
366
}
else
if
(
action
->
menu
() !=
nullptr
) {
// action got its menu created, remove item
367
model
->
removeRow
(
row
);
368
}
else
{
369
// action text or icon changed, update item
370
model
->
update
(
row
);
371
}
372
}
373
374
QDesignerFormEditorInterface
*
ActionEditor
::
core
()
const
375
{
376
return
m_core
;
377
}
378
379
QString
ActionEditor
::
filter
()
const
380
{
381
return
m_filter
;
382
}
383
384
void
ActionEditor
::
setFilter
(
const
QString
&
f
)
385
{
386
m_filter
=
f
;
387
m_actionView
->
filter
(
m_filter
);
388
}
389
390
// Set changed state of icon property, reset when icon is cleared
391
static
void
refreshIconPropertyChanged
(
const
QAction *action,
QDesignerPropertySheetExtension
*sheet)
392
{
393
sheet->setChanged(sheet->indexOf(iconPropertyC), !action->icon().isNull());
394
}
395
396
void
ActionEditor
::
manageAction
(
QAction
*
action
)
397
{
398
action
->
setParent
(
formWindow
()->
mainContainer
());
399
core
()->
metaDataBase
()->
add
(
action
);
400
401
if
(
action
->
isSeparator
() ||
action
->
menu
() !=
nullptr
)
402
return
;
403
404
QDesignerPropertySheetExtension
*
sheet
=
qt_extension
<
QDesignerPropertySheetExtension
*>(
core
()->
extensionManager
(),
action
);
405
sheet
->
setChanged
(
sheet
->
indexOf
(
objectNamePropertyC
),
true
);
406
sheet
->
setChanged
(
sheet
->
indexOf
(
textPropertyC
),
true
);
407
refreshIconPropertyChanged
(
action
,
sheet
);
408
409
m_actionView
->
setCurrentIndex
(
m_actionView
->
model
()->
addAction
(
action
));
410
connect
(
action
, &
QAction
::
changed
,
this
, &
ActionEditor
::
slotActionChanged
);
411
}
412
413
void
ActionEditor
::
unmanageAction
(
QAction
*
action
)
414
{
415
core
()->
metaDataBase
()->
remove
(
action
);
416
action
->
setParent
(
nullptr
);
417
418
disconnect
(
action
, &
QAction
::
changed
,
this
, &
ActionEditor
::
slotActionChanged
);
419
420
const
int
row
=
m_actionView
->
model
()->
findAction
(
action
);
421
if
(
row
!= -1)
422
m_actionView
->
model
()->
remove
(
row
);
423
}
424
425
// Set an initial property and mark it as changed in the sheet
426
static
void
setInitialProperty
(
QDesignerPropertySheetExtension
*sheet,
const
QString &name,
const
QVariant &value)
427
{
428
const
int
index = sheet->indexOf(name);
429
Q_ASSERT(index != -1);
430
sheet->setProperty(index, value);
431
sheet->setChanged(index,
true
);
432
}
433
434
void
ActionEditor
::
slotNewAction
()
435
{
436
NewActionDialog
dlg
(
this
);
437
dlg
.
setWindowTitle
(
tr
(
"New action"
));
438
439
if
(
dlg
.
exec
() ==
QDialog
::
Accepted
) {
440
const
ActionData
actionData
=
dlg
.
actionData
();
441
m_actionView
->
clearSelection
();
442
QAction
*
action
=
new
QAction
(
formWindow
());
443
action
->
setObjectName
(
actionData
.
name
);
444
formWindow
()->
ensureUniqueObjectName
(
action
);
445
action
->
setText
(
actionData
.
text
);
446
447
QDesignerPropertySheetExtension
*
sheet
=
qt_extension
<
QDesignerPropertySheetExtension
*>(
core
()->
extensionManager
(),
action
);
448
if
(!
actionData
.
toolTip
.
isEmpty
())
449
setInitialProperty
(
sheet
,
toolTipPropertyC
,
actionData
.
toolTip
);
450
451
if
(
actionData
.
checkable
)
452
setInitialProperty
(
sheet
,
checkablePropertyC
,
QVariant
(
true
));
453
454
if
(!
actionData
.
keysequence
.
value
().
isEmpty
())
455
setInitialProperty
(
sheet
,
shortcutPropertyC
,
QVariant
::
fromValue
(
actionData
.
keysequence
));
456
457
sheet
->
setProperty
(
sheet
->
indexOf
(
iconPropertyC
),
QVariant
::
fromValue
(
actionData
.
icon
));
458
459
setInitialProperty
(
sheet
,
menuRolePropertyC
,
QVariant
::
fromValue
(
actionData
.
menuRole
));
460
461
AddActionCommand
*
cmd
=
new
AddActionCommand
(
formWindow
());
462
cmd
->
init
(
action
);
463
formWindow
()->
commandHistory
()->
push
(
cmd
);
464
}
465
}
466
467
// return a FormWindow command to apply an icon or a reset command in case it
468
// is empty.
469
470
static
QDesignerFormWindowCommand *
setIconPropertyCommand
(
const
PropertySheetIconValue &newIcon, QAction *action, QDesignerFormWindowInterface *fw)
471
{
472
const
QString iconProperty = iconPropertyC;
473
if
(newIcon.isEmpty()) {
474
ResetPropertyCommand *cmd =
new
ResetPropertyCommand(fw);
475
cmd->init(action, iconProperty);
476
return
cmd;
477
}
478
SetPropertyCommand *cmd =
new
SetPropertyCommand(fw);
479
cmd->init(action, iconProperty, QVariant::fromValue(newIcon));
480
return
cmd;
481
}
482
483
// return a FormWindow command to apply a QKeySequence or a reset command
484
// in case it is empty.
485
486
static
QDesignerFormWindowCommand *
setKeySequencePropertyCommand
(
const
PropertySheetKeySequenceValue &ks, QAction *action, QDesignerFormWindowInterface *fw)
487
{
488
const
QString shortcutProperty = shortcutPropertyC;
489
if
(ks.value().isEmpty()) {
490
ResetPropertyCommand *cmd =
new
ResetPropertyCommand(fw);
491
cmd->init(action, shortcutProperty);
492
return
cmd;
493
}
494
SetPropertyCommand *cmd =
new
SetPropertyCommand(fw);
495
cmd->init(action, shortcutProperty, QVariant::fromValue(ks));
496
return
cmd;
497
}
498
499
// return a FormWindow command to apply a POD value or reset command in case
500
// it is equal to the default value.
501
502
template
<
class
T>
503
QDesignerFormWindowCommand *
setPropertyCommand
(
const
QString &name, T value, T defaultValue,
504
QObject *o, QDesignerFormWindowInterface *fw)
505
{
506
if
(value == defaultValue) {
507
ResetPropertyCommand *cmd =
new
ResetPropertyCommand(fw);
508
cmd->init(o, name);
509
return
cmd;
510
}
511
SetPropertyCommand *cmd =
new
SetPropertyCommand(fw);
512
cmd->init(o, name, QVariant(value));
513
return
cmd;
514
}
515
516
// Return the text value of a string property via PropertySheetStringValue
517
static
inline
QString
textPropertyValue
(
const
QDesignerPropertySheetExtension
*sheet,
const
QString &name)
518
{
519
const
int
index = sheet->indexOf(name);
520
Q_ASSERT(index != -1);
521
const
PropertySheetStringValue ps = qvariant_cast<
PropertySheetStringValue
>(sheet->property(index));
522
return
ps.value();
523
}
524
525
void
ActionEditor
::
editAction
(
QAction
*
action
,
int
column
)
526
{
527
if
(!
action
)
528
return
;
529
530
NewActionDialog
dlg
(
this
);
531
dlg
.
setWindowTitle
(
tr
(
"Edit action"
));
532
533
ActionData
oldActionData
;
534
QDesignerPropertySheetExtension
*
sheet
=
qt_extension
<
QDesignerPropertySheetExtension
*>(
core
()->
extensionManager
(),
action
);
535
oldActionData
.
name
=
action
->
objectName
();
536
oldActionData
.
text
=
action
->
text
();
537
oldActionData
.
toolTip
=
textPropertyValue
(
sheet
,
toolTipPropertyC
);
538
oldActionData
.
icon
=
qvariant_cast
<
PropertySheetIconValue
>(
sheet
->
property
(
sheet
->
indexOf
(
iconPropertyC
)));
539
oldActionData
.
keysequence
=
ActionModel
::
actionShortCut
(
sheet
);
540
oldActionData
.
checkable
=
action
->
isCheckable
();
541
oldActionData
.
menuRole
.
value
=
action
->
menuRole
();
542
dlg
.
setActionData
(
oldActionData
);
543
544
switch
(
column
) {
545
case
qdesigner_internal
::
ActionModel
::
NameColumn
:
546
dlg
.
focusName
();
547
break
;
548
case
qdesigner_internal
::
ActionModel
::
TextColumn
:
549
dlg
.
focusText
();
550
break
;
551
case
qdesigner_internal
::
ActionModel
::
ShortCutColumn
:
552
dlg
.
focusShortcut
();
553
break
;
554
case
qdesigner_internal
::
ActionModel
::
CheckedColumn
:
555
dlg
.
focusCheckable
();
556
break
;
557
case
qdesigner_internal
::
ActionModel
::
ToolTipColumn
:
558
dlg
.
focusTooltip
();
559
break
;
560
case
qdesigner_internal
::
ActionModel
::
MenuRoleColumn
:
561
dlg
.
focusMenuRole
();
562
break
;
563
}
564
565
if
(!
dlg
.
exec
())
566
return
;
567
568
// figure out changes and whether to start a macro
569
const
ActionData
newActionData
=
dlg
.
actionData
();
570
const
unsigned
changeMask
=
newActionData
.
compare
(
oldActionData
);
571
if
(
changeMask
== 0u)
572
return
;
573
574
const
bool
severalChanges
= (
changeMask
!=
ActionData
::
TextChanged
) && (
changeMask
!=
ActionData
::
NameChanged
)
575
&& (
changeMask
!=
ActionData
::
ToolTipChanged
) && (
changeMask
!=
ActionData
::
IconChanged
)
576
&& (
changeMask
!=
ActionData
::
CheckableChanged
) && (
changeMask
!=
ActionData
::
KeysequenceChanged
)
577
&& (
changeMask
!=
ActionData
::
MenuRoleChanged
);
578
579
QDesignerFormWindowInterface
*
fw
=
formWindow
();
580
QUndoStack
*
undoStack
=
fw
->
commandHistory
();
581
if
(
severalChanges
)
582
fw
->
beginCommand
(u"Edit action"_s);
583
584
if
(
changeMask
&
ActionData
::
NameChanged
)
585
undoStack
->
push
(
createTextPropertyCommand
(
objectNamePropertyC
,
newActionData
.
name
,
action
,
fw
));
586
587
if
(
changeMask
&
ActionData
::
TextChanged
)
588
undoStack
->
push
(
createTextPropertyCommand
(
textPropertyC
,
newActionData
.
text
,
action
,
fw
));
589
590
if
(
changeMask
&
ActionData
::
ToolTipChanged
)
591
undoStack
->
push
(
createTextPropertyCommand
(
toolTipPropertyC
,
newActionData
.
toolTip
,
action
,
fw
));
592
593
if
(
changeMask
&
ActionData
::
IconChanged
)
594
undoStack
->
push
(
setIconPropertyCommand
(
newActionData
.
icon
,
action
,
fw
));
595
596
if
(
changeMask
&
ActionData
::
CheckableChanged
)
597
undoStack
->
push
(
setPropertyCommand
(
checkablePropertyC
,
newActionData
.
checkable
,
false
,
action
,
fw
));
598
599
if
(
changeMask
&
ActionData
::
KeysequenceChanged
)
600
undoStack
->
push
(
setKeySequencePropertyCommand
(
newActionData
.
keysequence
,
action
,
fw
));
601
602
if
(
changeMask
&
ActionData
::
MenuRoleChanged
)
603
undoStack
->
push
(
setPropertyCommand
(
menuRolePropertyC
,
static_cast
<
QAction
::
MenuRole
>(
newActionData
.
menuRole
.
value
),
QAction
::
NoRole
,
action
,
fw
));
604
605
if
(
severalChanges
)
606
fw
->
endCommand
();
607
}
608
609
void
ActionEditor
::
editCurrentAction
()
610
{
611
if
(
QAction
*
a
=
m_actionView
->
currentAction
())
612
editAction
(
a
);
613
}
614
615
void
ActionEditor
::
navigateToSlotCurrentAction
()
616
{
617
if
(
QAction
*
a
=
m_actionView
->
currentAction
())
618
QDesignerTaskMenu
::
navigateToSlot
(
m_core
,
a
, u"triggered()"_s);
619
}
620
621
void
ActionEditor
::
deleteActions
(
QDesignerFormWindowInterface
*
fw
,
const
ActionList
&
actions
)
622
{
623
// We need a macro even in the case of single action because the commands might cause the
624
// scheduling of other commands (signal slots connections)
625
const
QString
description
=
actions
.
size
() == 1
626
?
tr
(
"Remove action '%1'"
).
arg
(
actions
.
constFirst
()->
objectName
())
627
:
tr
(
"Remove actions"
);
628
fw
->
beginCommand
(
description
);
629
for
(
QAction
*
action
:
actions
) {
630
RemoveActionCommand
*
cmd
=
new
RemoveActionCommand
(
fw
);
631
cmd
->
init
(
action
);
632
fw
->
commandHistory
()->
push
(
cmd
);
633
}
634
fw
->
endCommand
();
635
}
636
637
#
if
QT_CONFIG
(
clipboard
)
638
void
ActionEditor
::
copyActions
(
QDesignerFormWindowInterface
*
fwi
,
const
ActionList
&
actions
)
639
{
640
FormWindowBase
*
fw
=
qobject_cast
<
FormWindowBase
*>(
fwi
);
641
if
(!
fw
)
642
return
;
643
644
FormBuilderClipboard
clipboard
;
645
clipboard
.
m_actions
=
actions
;
646
647
if
(
clipboard
.
empty
())
648
return
;
649
650
QEditorFormBuilder
*
formBuilder
=
fw
->
createFormBuilder
();
651
Q_ASSERT
(
formBuilder
);
652
653
QBuffer
buffer
;
654
if
(
buffer
.
open
(
QIODevice
::
WriteOnly
))
655
if
(
formBuilder
->
copy
(&
buffer
,
clipboard
))
656
qApp
->
clipboard
()->
setText
(
QString
::
fromUtf8
(
buffer
.
buffer
()),
QClipboard
::
Clipboard
);
657
delete
formBuilder
;
658
}
659
#
endif
660
661
void
ActionEditor
::
slotDelete
()
662
{
663
QDesignerFormWindowInterface
*
fw
=
formWindow
();
664
if
(!
fw
)
665
return
;
666
667
const
ActionView
::
ActionList
selection
=
m_actionView
->
selectedActions
();
668
if
(
selection
.
isEmpty
())
669
return
;
670
671
deleteActions
(
fw
,
selection
);
672
}
673
674
// UnderScore: "Open file" -> actionOpen_file
675
static
QString
underscore
(QString text)
676
{
677
static
const
QRegularExpression nonAsciiPattern(u"[^a-zA-Z_0-9]"_s);
678
Q_ASSERT(nonAsciiPattern.isValid());
679
text.replace(nonAsciiPattern,
"_"_L1
);
680
static
const
QRegularExpression multipleSpacePattern(u"__*"_s);
681
Q_ASSERT(multipleSpacePattern.isValid());
682
text.replace(multipleSpacePattern,
"_"_L1
);
683
if
(text.endsWith(u'_'))
684
text.chop(1);
685
return
text;
686
}
687
688
// CamelCase: "Open file" -> actionOpenFile, ignoring non-ASCII letters.
689
690
enum
CharacterCategory
{
OtherCharacter
,
DigitOrAsciiLetter
,
NonAsciiLetter
};
691
692
static
inline
CharacterCategory
category
(QChar c)
693
{
694
if
(c.isDigit())
695
return
DigitOrAsciiLetter
;
696
if
(c.isLetter()) {
697
const
ushort uc = c.unicode();
698
return
(uc >=
'a'
&& uc <=
'z'
) || (uc >=
'A'
&& uc <=
'Z'
)
699
?
DigitOrAsciiLetter
:
NonAsciiLetter
;
700
}
701
return
OtherCharacter
;
702
}
703
704
static
QString
camelCase
(
const
QString &text)
705
{
706
QString result;
707
result.reserve(text.size());
708
bool
lastCharAccepted =
false
;
709
for
(QChar c : text) {
710
const
CharacterCategory cat = category(c);
711
if
(cat != NonAsciiLetter) {
712
const
bool
acceptable = cat == DigitOrAsciiLetter;
713
if
(acceptable)
714
result.append(lastCharAccepted ? c : c.toUpper());
// New word starts
715
lastCharAccepted = acceptable;
716
}
717
}
718
return
result;
719
}
720
721
QString
ActionEditor
::
actionTextToName
(
const
QString
&
text
,
const
QString
&
prefix
)
722
{
723
QString
name
=
text
;
724
if
(
name
.
isEmpty
())
725
return
QString
();
726
return
prefix
+ (
m_objectNamingMode
==
CamelCase
?
camelCase
(
text
) :
underscore
(
text
));
727
728
}
729
730
void
ActionEditor
::
resourceImageDropped
(
const
QString
&
path
,
QAction
*
action
)
731
{
732
QDesignerFormWindowInterface
*
fw
=
formWindow
();
733
if
(!
fw
)
734
return
;
735
736
QDesignerPropertySheetExtension
*
sheet
=
qt_extension
<
QDesignerPropertySheetExtension
*>(
core
()->
extensionManager
(),
action
);
737
const
PropertySheetIconValue
oldIcon
=
738
qvariant_cast
<
PropertySheetIconValue
>(
sheet
->
property
(
sheet
->
indexOf
(
iconPropertyC
)));
739
PropertySheetIconValue
newIcon
;
740
newIcon
.
setPixmap
(
QIcon
::
Normal
,
QIcon
::
Off
,
PropertySheetPixmapValue
(
path
));
741
if
(
newIcon
.
paths
().
isEmpty
() ||
newIcon
.
paths
() ==
oldIcon
.
paths
())
742
return
;
743
744
fw
->
commandHistory
()->
push
(
setIconPropertyCommand
(
newIcon
,
action
,
fw
));
745
}
746
747
void
ActionEditor
::
mainContainerChanged
()
748
{
749
// Invalidate references to objects kept in model
750
if
(
sender
() ==
formWindow
())
751
setFormWindow
(
nullptr
);
752
}
753
754
void
ActionEditor
::
clearSelection
()
755
{
756
// For use by the menu editor; block the syncing of the object inspector
757
// in slotCurrentItemChanged() since the menu editor updates it itself.
758
m_withinSelectAction
=
true
;
759
m_actionView
->
clearSelection
();
760
m_withinSelectAction
=
false
;
761
}
762
763
void
ActionEditor
::
selectAction
(
QAction
*
a
)
764
{
765
// For use by the menu editor; block the syncing of the object inspector
766
// in slotCurrentItemChanged() since the menu editor updates it itself.
767
m_withinSelectAction
=
true
;
768
m_actionView
->
selectAction
(
a
);
769
m_withinSelectAction
=
false
;
770
}
771
772
void
ActionEditor
::
slotViewMode
(
QAction
*
a
)
773
{
774
m_actionView
->
setViewMode
(
a
->
data
().
toInt
());
775
updateViewModeActions
();
776
}
777
778
void
ActionEditor
::
slotSelectAssociatedWidget
(
QWidget
*
w
)
779
{
780
QDesignerFormWindowInterface
*
fw
=
formWindow
();
781
if
(!
fw
)
782
return
;
783
784
QDesignerObjectInspector
*
oi
=
qobject_cast
<
QDesignerObjectInspector
*>(
core
()->
objectInspector
());
785
if
(!
oi
)
786
return
;
787
788
fw
->
clearSelection
();
// Actually, there are no widgets selected due to focus in event handling. Just to be sure.
789
oi
->
selectObject
(
w
);
790
}
791
792
void
ActionEditor
::
restoreSettings
()
793
{
794
QDesignerSettingsInterface
*
settings
=
m_core
->
settingsManager
();
795
m_actionView
->
setViewMode
(
settings
->
value
(
actionEditorViewModeKey
, 0).
toInt
());
796
updateViewModeActions
();
797
}
798
799
void
ActionEditor
::
saveSettings
()
800
{
801
QDesignerSettingsInterface
*
settings
=
m_core
->
settingsManager
();
802
settings
->
setValue
(
actionEditorViewModeKey
,
m_actionView
->
viewMode
());
803
}
804
805
void
ActionEditor
::
updateViewModeActions
()
806
{
807
switch
(
m_actionView
->
viewMode
()) {
808
case
ActionView
::
IconView
:
809
m_iconViewAction
->
setChecked
(
true
);
810
break
;
811
case
ActionView
::
DetailedView
:
812
m_listViewAction
->
setChecked
(
true
);
813
break
;
814
}
815
}
816
817
#
if
QT_CONFIG
(
clipboard
)
818
void
ActionEditor
::
slotCopy
()
819
{
820
QDesignerFormWindowInterface
*
fw
=
formWindow
();
821
if
(!
fw
)
822
return
;
823
824
const
ActionView
::
ActionList
selection
=
m_actionView
->
selectedActions
();
825
if
(
selection
.
isEmpty
())
826
return
;
827
828
copyActions
(
fw
,
selection
);
829
}
830
831
void
ActionEditor
::
slotCut
()
832
{
833
QDesignerFormWindowInterface
*
fw
=
formWindow
();
834
if
(!
fw
)
835
return
;
836
837
const
ActionView
::
ActionList
selection
=
m_actionView
->
selectedActions
();
838
if
(
selection
.
isEmpty
())
839
return
;
840
841
copyActions
(
fw
,
selection
);
842
deleteActions
(
fw
,
selection
);
843
}
844
845
void
ActionEditor
::
slotPaste
()
846
{
847
FormWindowBase
*
fw
=
qobject_cast
<
FormWindowBase
*>(
formWindow
());
848
if
(!
fw
)
849
return
;
850
m_actionView
->
clearSelection
();
851
fw
->
paste
(
FormWindowBase
::
PasteActionsOnly
);
852
}
853
#
endif
854
855
void
ActionEditor
::
slotContextMenuRequested
(
QContextMenuEvent
*
e
,
QAction
*
item
)
856
{
857
QMenu
menu
(
this
);
858
menu
.
addAction
(
m_actionNew
);
859
menu
.
addSeparator
();
860
menu
.
addAction
(
m_actionEdit
);
861
if
(
QDesignerTaskMenu
::
isSlotNavigationEnabled
(
m_core
))
862
menu
.
addAction
(
m_actionNavigateToSlot
);
863
864
// Associated Widgets
865
if
(
QAction
*
action
=
m_actionView
->
currentAction
()) {
866
const
QWidgetList
associatedWidgets
=
ActionModel
::
associatedWidgets
(
action
);
867
if
(!
associatedWidgets
.
isEmpty
()) {
868
QMenu
*
associatedWidgetsSubMenu
=
menu
.
addMenu
(
tr
(
"Used In"
));
869
for
(
QWidget
*
w
:
associatedWidgets
) {
870
associatedWidgetsSubMenu
->
addAction
(
w
->
objectName
(),
871
this
, [
this
,
w
] {
this
->
slotSelectAssociatedWidget
(
w
); });
872
}
873
}
874
}
875
876
menu
.
addSeparator
();
877
#
if
QT_CONFIG
(
clipboard
)
878
menu
.
addAction
(
m_actionCut
);
879
menu
.
addAction
(
m_actionCopy
);
880
menu
.
addAction
(
m_actionPaste
);
881
#
endif
882
menu
.
addAction
(
m_actionSelectAll
);
883
menu
.
addAction
(
m_actionDelete
);
884
menu
.
addSeparator
();
885
menu
.
addAction
(
m_iconViewAction
);
886
menu
.
addAction
(
m_listViewAction
);
887
888
emit
contextMenuRequested
(&
menu
,
item
);
889
890
menu
.
exec
(
e
->
globalPos
());
891
e
->
accept
();
892
}
893
894
}
// namespace qdesigner_internal
895
896
QT_END_NAMESPACE
toolTipPropertyC
static constexpr auto toolTipPropertyC
Definition
actioneditor.cpp:58
iconPropertyC
static constexpr auto iconPropertyC
Definition
actioneditor.cpp:55
textPropertyC
static constexpr auto textPropertyC
Definition
actioneditor.cpp:61
shortcutPropertyC
static constexpr auto shortcutPropertyC
Definition
actioneditor.cpp:56
menuRolePropertyC
static constexpr auto menuRolePropertyC
Definition
actioneditor.cpp:57
actionEditorViewModeKey
static constexpr auto actionEditorViewModeKey
Definition
actioneditor.cpp:53
objectNamePropertyC
static constexpr auto objectNamePropertyC
Definition
actioneditor.cpp:60
checkablePropertyC
static constexpr auto checkablePropertyC
Definition
actioneditor.cpp:59
QDesignerPropertySheetExtension
Definition
propertysheet.h:15
QPaintEngine::QPainter
friend class QPainter
Definition
qpaintengine.h:220
qdesigner_internal::ActionGroupDelegate
Definition
actioneditor.cpp:66
qdesigner_internal::ActionGroupDelegate::drawFocus
void drawFocus(QPainter *, const QStyleOptionViewItem &, const QRect &) const override
Renders the region within the rectangle specified by rect, indicating that it has the focus,...
Definition
actioneditor.cpp:79
qdesigner_internal::ActionGroupDelegate::paint
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
This pure abstract function must be reimplemented if you want to provide custom rendering.
Definition
actioneditor.cpp:71
qdesigner_internal::ActionGroupDelegate::ActionGroupDelegate
ActionGroupDelegate(QObject *parent)
Definition
actioneditor.cpp:68
qdesigner_internal::PropertySheetStringValue
Definition
qdesigner_utils_p.h:385
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::setKeySequencePropertyCommand
static QDesignerFormWindowCommand * setKeySequencePropertyCommand(const PropertySheetKeySequenceValue &ks, QAction *action, QDesignerFormWindowInterface *fw)
Definition
actioneditor.cpp:486
qdesigner_internal::CharacterCategory
CharacterCategory
Definition
actioneditor.cpp:690
qdesigner_internal::OtherCharacter
@ OtherCharacter
Definition
actioneditor.cpp:690
qdesigner_internal::NonAsciiLetter
@ NonAsciiLetter
Definition
actioneditor.cpp:690
qdesigner_internal::DigitOrAsciiLetter
@ DigitOrAsciiLetter
Definition
actioneditor.cpp:690
qdesigner_internal::category
static CharacterCategory category(QChar c)
Definition
actioneditor.cpp:692
qdesigner_internal::setIconPropertyCommand
static QDesignerFormWindowCommand * setIconPropertyCommand(const PropertySheetIconValue &newIcon, QAction *action, QDesignerFormWindowInterface *fw)
Definition
actioneditor.cpp:470
qdesigner_internal::setInitialProperty
static void setInitialProperty(QDesignerPropertySheetExtension *sheet, const QString &name, const QVariant &value)
Definition
actioneditor.cpp:426
qdesigner_internal::refreshIconPropertyChanged
static void refreshIconPropertyChanged(const QAction *action, QDesignerPropertySheetExtension *sheet)
Definition
actioneditor.cpp:391
qdesigner_internal::underscore
static QString underscore(QString text)
Definition
actioneditor.cpp:675
qdesigner_internal::textPropertyValue
static QString textPropertyValue(const QDesignerPropertySheetExtension *sheet, const QString &name)
Definition
actioneditor.cpp:517
qdesigner_internal::camelCase
static QString camelCase(const QString &text)
Definition
actioneditor.cpp:704
qdesigner_internal::setPropertyCommand
QDesignerFormWindowCommand * setPropertyCommand(const QString &name, T value, T defaultValue, QObject *o, QDesignerFormWindowInterface *fw)
Definition
actioneditor.cpp:503
qttools
src
designer
src
lib
shared
actioneditor.cpp
Generated on
for Qt by
1.18.0