Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
button_taskmenu.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
6#include <qdesigner_formwindowcommand_p.h>
7#include <formwindowbase_p.h>
8
9#include <QtDesigner/abstractformwindow.h>
10#include <QtDesigner/abstractformwindowcursor.h>
11#include <QtDesigner/abstractformeditor.h>
12#include <QtDesigner/abstractmetadatabase.h>
13#include <QtDesigner/abstractobjectinspector.h>
14#include <QtDesigner/abstractpropertyeditor.h>
15
16#include <QtWidgets/qmenu.h>
17#include <QtWidgets/qstyle.h>
18#include <QtWidgets/qstyleoption.h>
19#include <QtWidgets/qabstractbutton.h>
20#include <QtWidgets/qbuttongroup.h>
21#include <QtWidgets/qapplication.h>
22
23#include <QtGui/qaction.h>
24#include <QtGui/qactiongroup.h>
25
26#include <QtCore/qdebug.h>
27
28Q_DECLARE_METATYPE(QButtonGroup*)
29
30QT_BEGIN_NAMESPACE
31
32using namespace Qt::StringLiterals;
33
34namespace qdesigner_internal {
35
36enum { debugButtonMenu = 0 };
37
40
41// ButtonGroupCommand: Base for commands handling button groups and button lists
42// addButtonsToGroup() and removeButtonsFromGroup() are low-level helpers for
43// adding/removing members to/from existing groups.
44//
45// createButtonGroup()/breakButtonGroup() create and remove the groups from scratch.
46// When using them in a command, the command must be executed within
47// a macro since it makes the form emit objectRemoved() which might cause other components
48// to add commands (for example, removal of signals and slots)
50
51protected:
52 ButtonGroupCommand(const QString &description, QDesignerFormWindowInterface *formWindow);
53
54 void initialize(const ButtonList &bl, QButtonGroup *buttonGroup);
55
56 // Helper: Add the buttons to the group
58 // Helper; Remove the buttons
60
61 // Create the button group in Designer
63 // Remove the button group from Designer
65
66public:
67 static QString nameList(const ButtonList& bl);
68 static ButtonGroupList managedButtonGroups(const QDesignerFormWindowInterface *formWindow);
69
70private:
71 ButtonList m_buttonList;
72 QButtonGroup *m_buttonGroup;
73};
74
75ButtonGroupCommand::ButtonGroupCommand(const QString &description, QDesignerFormWindowInterface *formWindow) :
77 m_buttonGroup(nullptr)
78{
79}
80
81void ButtonGroupCommand::initialize(const ButtonList &bl, QButtonGroup *buttonGroup)
82{
83 m_buttonList = bl;
84 m_buttonGroup = buttonGroup;
85}
86
88{
89 if (debugButtonMenu)
90 qDebug() << "Adding " << m_buttonList << " to " << m_buttonGroup;
91 for (auto *b : std::as_const(m_buttonList))
92 m_buttonGroup->addButton(b);
93}
94
96{
97 if (debugButtonMenu)
98 qDebug() << "Removing " << m_buttonList << " from " << m_buttonGroup;
99 for (auto *b : std::as_const(m_buttonList))
100 m_buttonGroup->removeButton(b);
101}
102
104{
105 if (debugButtonMenu)
106 qDebug() << "Creating " << m_buttonGroup << " from " << m_buttonList;
107
108 QDesignerFormWindowInterface *fw = formWindow();
109 QDesignerFormEditorInterface *core = fw->core();
110 core->metaDataBase()->add(m_buttonGroup);
112 // Make button group visible
113 core->objectInspector()->setFormWindow(fw);
114}
115
117{
118 if (debugButtonMenu)
119 qDebug() << "Removing " << m_buttonGroup << " consisting of " << m_buttonList;
120
121 QDesignerFormWindowInterface *fw = formWindow();
122 QDesignerFormEditorInterface *core = fw->core();
123 // Button group was selected, that is, break was invoked via its context menu. Remove it from property editor, select the buttons
124 if (core->propertyEditor()->object() == m_buttonGroup) {
125 fw->clearSelection(false);
126 for (auto *b : std::as_const(m_buttonList))
127 fw->selectWidget(b, true);
128 }
129 // Now remove and refresh object inspector
131 // Notify components (for example, signal slot editor)
132 if (qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(fw))
133 fwb->emitObjectRemoved(m_buttonGroup);
134 core->metaDataBase()->remove(m_buttonGroup);
135 core->objectInspector()->setFormWindow(fw);
136}
137
138QString ButtonGroupCommand::nameList(const ButtonList& bl)
139{
140 QString rc;
141 const QChar quote = QLatin1Char('\'');
142 const auto separator = ", "_L1;
143 for (qsizetype i = 0, size = bl.size(); i < size; ++i) {
144 if (i)
145 rc += separator;
146 rc += quote;
147 rc += bl.at(i)->objectName();
148 rc += quote;
149 }
150 return rc;
151
152}
153
154ButtonGroupList ButtonGroupCommand::managedButtonGroups(const QDesignerFormWindowInterface *formWindow)
155{
156 const QDesignerMetaDataBaseInterface *mdb = formWindow->core()->metaDataBase();
157 ButtonGroupList bl;
158 // Check 1st order children for managed button groups
159 for (auto *o : formWindow->mainContainer()->children()) {
160 if (!o->isWidgetType()) {
161 if (QButtonGroup *bg = qobject_cast<QButtonGroup *>(o)) {
162 if (mdb->item(bg))
163 bl.push_back(bg);
164 }
165 }
166 }
167 return bl;
168}
169
170// --------------- CreateButtonGroupCommand
171// This command might be executed in a macro with a remove
172// command to move buttons from one group to a new one.
174public:
175 CreateButtonGroupCommand(QDesignerFormWindowInterface *formWindow);
176 bool init(const ButtonList &bl);
177
180};
181
182CreateButtonGroupCommand::CreateButtonGroupCommand(QDesignerFormWindowInterface *formWindow) :
183 ButtonGroupCommand(QApplication::translate("Command", "Create button group"), formWindow)
184{
185}
186
187bool CreateButtonGroupCommand::init(const ButtonList &bl)
188{
189 if (bl.isEmpty())
190 return false;
191 QDesignerFormWindowInterface *fw = formWindow();
192 QButtonGroup *buttonGroup = new QButtonGroup(fw->mainContainer());
193 buttonGroup->setObjectName(u"buttonGroup"_s);
194 fw->ensureUniqueObjectName(buttonGroup);
195 initialize(bl, buttonGroup);
196 return true;
197}
198
199// --------------- BreakButtonGroupCommand
201public:
202 BreakButtonGroupCommand(QDesignerFormWindowInterface *formWindow);
203 bool init(QButtonGroup *group);
204
207};
208
209BreakButtonGroupCommand::BreakButtonGroupCommand(QDesignerFormWindowInterface *formWindow) :
210 ButtonGroupCommand(QApplication::translate("Command", "Break button group"), formWindow)
211{
212}
213
214bool BreakButtonGroupCommand::init(QButtonGroup *group)
215{
216 if (!group)
217 return false;
218 initialize(group->buttons(), group);
219 setText(QApplication::translate("Command", "Break button group '%1'").arg(group->objectName()));
220 return true;
221}
222
223// --------------- AddButtonsToGroupCommand
224// This command might be executed in a macro with a remove
225// command to move buttons from one group to a new one.
227public:
228 AddButtonsToGroupCommand(QDesignerFormWindowInterface *formWindow);
229 void init(const ButtonList &bl, QButtonGroup *group);
230
233};
234
235AddButtonsToGroupCommand::AddButtonsToGroupCommand(QDesignerFormWindowInterface *formWindow) :
236 ButtonGroupCommand(QApplication::translate("Command", "Add buttons to group"), formWindow)
237{
238}
239
240void AddButtonsToGroupCommand::init(const ButtonList &bl, QButtonGroup *group)
241{
242 initialize(bl, group);
243 //: Command description for adding buttons to a QButtonGroup
244 setText(QApplication::translate("Command", "Add '%1' to '%2'").arg(nameList(bl), group->objectName()));
245}
246
247//-------------------- RemoveButtonsFromGroupCommand
249public:
250 RemoveButtonsFromGroupCommand(QDesignerFormWindowInterface *formWindow);
251 bool init(const ButtonList &bl);
252
255};
256
257RemoveButtonsFromGroupCommand::RemoveButtonsFromGroupCommand(QDesignerFormWindowInterface *formWindow) :
258 ButtonGroupCommand(QApplication::translate("Command", "Remove buttons from group"), formWindow)
259{
260}
261
262bool RemoveButtonsFromGroupCommand::init(const ButtonList &bl)
263{
264 if (bl.isEmpty())
265 return false;
266 QButtonGroup *group = bl.constFirst()->group();
267 if (!group)
268 return false;
269 if (bl.size() >= group->buttons().size())
270 return false;
271 initialize(bl, group);
272 //: Command description for removing buttons from a QButtonGroup
273 setText(QApplication::translate("Command", "Remove '%1' from '%2'").arg(nameList(bl), group->objectName()));
274 return true;
275}
276
277// -------- ButtonGroupMenu
278ButtonGroupMenu::ButtonGroupMenu(QObject *parent) :
279 QObject(parent),
280 m_selectGroupAction(new QAction(tr("Select members"), this)),
281 m_breakGroupAction(new QAction(tr("Break"), this))
282{
283 connect(m_breakGroupAction, &QAction::triggered, this, &ButtonGroupMenu::breakGroup);
284 connect(m_selectGroupAction, &QAction::triggered, this, &ButtonGroupMenu::selectGroup);
285}
286
287void ButtonGroupMenu::initialize(QDesignerFormWindowInterface *formWindow, QButtonGroup *buttonGroup, QAbstractButton *currentButton)
288{
289 m_buttonGroup = buttonGroup;
290 m_currentButton = currentButton;
291 m_formWindow = formWindow;
292 Q_ASSERT(m_formWindow);
293
294 const bool canBreak = buttonGroup != nullptr;
295 m_breakGroupAction->setEnabled(canBreak);
296 m_selectGroupAction->setEnabled(canBreak);
297}
298
299void ButtonGroupMenu::selectGroup()
300{
301 // Select and make current button "current" again by selecting it last (if there is any)
302 const ButtonList buttons = m_buttonGroup->buttons();
303 m_formWindow->clearSelection(false);
304 for (auto *b : buttons) {
305 if (b != m_currentButton)
306 m_formWindow->selectWidget(b, true);
307 }
308 if (m_currentButton)
309 m_formWindow->selectWidget(m_currentButton, true);
310}
311
312void ButtonGroupMenu::breakGroup()
313{
315 if (cmd->init(m_buttonGroup)) {
316 // Need a macro since the command might trigger additional commands
317 QUndoStack *history = m_formWindow->commandHistory();
318 history->beginMacro(cmd->text());
319 history->push(cmd);
320 history->endMacro();
321 } else {
322 qWarning("** WARNING Failed to initialize BreakButtonGroupCommand!");
323 delete cmd;
324 }
325}
326
327// ButtonGroupTaskMenu
328ButtonGroupTaskMenu::ButtonGroupTaskMenu(QButtonGroup *buttonGroup, QObject *parent) :
329 QObject(parent),
330 m_buttonGroup(buttonGroup)
331{
332 m_taskActions.push_back(m_menu.breakGroupAction());
333 m_taskActions.push_back(m_menu.selectGroupAction());
334}
335
337{
338 return m_menu.selectGroupAction();
339}
340
342{
343 m_menu.initialize(QDesignerFormWindowInterface::findFormWindow(m_buttonGroup), m_buttonGroup);
344 return m_taskActions;
345}
346
347// -------- Text area editor
349{
350public:
351 ButtonTextTaskMenuInlineEditor(QAbstractButton *button, QObject *parent);
352
353protected:
354 QRect editRectangle() const override;
355};
356
357ButtonTextTaskMenuInlineEditor::ButtonTextTaskMenuInlineEditor(QAbstractButton *button, QObject *parent) :
359{
360}
361
363{
364 QWidget *w = widget();
365 QStyleOptionButton opt;
366 opt.initFrom(w);
367 return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
368}
369
370// -------- Command link button description editor
372{
373public:
374 LinkDescriptionTaskMenuInlineEditor(QAbstractButton *button, QObject *parent);
375
376protected:
377 QRect editRectangle() const override;
378};
379
382{
383}
384
386{
387 QWidget *w = widget(); // TODO: What is the exact description area?
388 QStyleOptionButton opt;
389 opt.initFrom(w);
390 return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
391}
392
393// ----------- ButtonTaskMenu:
394
395ButtonTaskMenu::ButtonTaskMenu(QAbstractButton *button, QObject *parent) :
396 QDesignerTaskMenu(button, parent),
397 m_assignGroupSubMenu(new QMenu),
398 m_assignActionGroup(nullptr),
399 m_assignToGroupSubMenuAction(new QAction(tr("Assign to button group"), this)),
400 m_currentGroupSubMenu(new QMenu),
401 m_currentGroupSubMenuAction(new QAction(tr("Button group"), this)),
402 m_createGroupAction(new QAction(tr("New button group"), this)),
403 m_preferredEditAction(new QAction(tr("Change text..."), this)),
404 m_removeFromGroupAction(new QAction(tr("None"), this))
405{
406 connect(m_createGroupAction, &QAction::triggered, this, &ButtonTaskMenu::createGroup);
407 TaskMenuInlineEditor *textEditor = new ButtonTextTaskMenuInlineEditor(button, this);
408 connect(m_preferredEditAction, &QAction::triggered, textEditor, &TaskMenuInlineEditor::editText);
409 connect(m_removeFromGroupAction, &QAction::triggered, this, &ButtonTaskMenu::removeFromGroup);
410
411 m_assignToGroupSubMenuAction->setMenu(m_assignGroupSubMenu);
412
413 m_currentGroupSubMenu->addAction(m_groupMenu.breakGroupAction());
414 m_currentGroupSubMenu->addAction(m_groupMenu.selectGroupAction());
415 m_currentGroupSubMenuAction->setMenu(m_currentGroupSubMenu);
416
417
418 m_taskActions.append(m_preferredEditAction);
419 m_taskActions.append(m_assignToGroupSubMenuAction);
420 m_taskActions.append(m_currentGroupSubMenuAction);
421 m_taskActions.append(createSeparator());
422}
423
425{
426 delete m_assignGroupSubMenu;
427 delete m_currentGroupSubMenu;
428}
429
431{
432 return m_preferredEditAction;
433}
434
435bool ButtonTaskMenu::refreshAssignMenu(const QDesignerFormWindowInterface *fw, int buttonCount, SelectionType st, QButtonGroup *currentGroup)
436{
437 // clear
438 if (m_assignActionGroup) {
439 delete m_assignActionGroup;
440 m_assignActionGroup = nullptr;
441 }
442 m_assignGroupSubMenu->clear();
443 if (st == OtherSelection)
444 return false;
445
446
447 // Assign to new: Need several
448 const bool canAssignToNewGroup = buttonCount > 1;
449 m_createGroupAction->setEnabled(canAssignToNewGroup);
450 if (canAssignToNewGroup)
451 m_assignGroupSubMenu->addAction(m_createGroupAction);
452
453 // Assign to other
454 const ButtonGroupList bl = ButtonGroupCommand::managedButtonGroups(fw);
455 // Groups: Any groups to add to except the current?
456 const auto groupCount = bl.size();
457 const bool hasAddGroups = groupCount > 1 || (groupCount == 1 && !bl.contains(currentGroup));
458 if (hasAddGroups) {
459 if (!m_assignGroupSubMenu->isEmpty())
460 m_assignGroupSubMenu->addSeparator();
461 // Create a new action group
462 m_assignActionGroup = new QActionGroup(this);
463 connect(m_assignActionGroup, &QActionGroup::triggered, this, &ButtonTaskMenu::addToGroup);
464 for (auto *bg : bl) {
465 if (bg != currentGroup) {
466 QAction *a = new QAction(bg->objectName(), m_assignGroupSubMenu);
467 a->setData(QVariant::fromValue(bg));
468 m_assignActionGroup->addAction(a);
469 m_assignGroupSubMenu->addAction(a);
470 }
471 }
472 }
473 // Can remove: A homogenous selection of another group that does not completely break it.
474 const bool canRemoveFromGroup = st == GroupedButtonSelection;
475 m_removeFromGroupAction->setEnabled(canRemoveFromGroup);
476 if (canRemoveFromGroup) {
477 if (!m_assignGroupSubMenu->isEmpty())
478 m_assignGroupSubMenu->addSeparator();
479 m_assignGroupSubMenu->addAction(m_removeFromGroupAction);
480 }
481 return !m_assignGroupSubMenu->isEmpty();
482}
483
485{
486 ButtonTaskMenu *ncThis = const_cast<ButtonTaskMenu*>(this);
487 QButtonGroup *buttonGroup = nullptr;
488
489 QDesignerFormWindowInterface *fw = formWindow();
490 const SelectionType st = selectionType(fw->cursor(), &buttonGroup);
491
492 m_groupMenu.initialize(fw, buttonGroup, button());
493 const bool hasAssignOptions = ncThis->refreshAssignMenu(fw, fw->cursor()->selectedWidgetCount(), st, buttonGroup);
494 m_assignToGroupSubMenuAction->setVisible(hasAssignOptions);
495 // add/remove
496 switch (st) {
497 case UngroupedButtonSelection:
498 case OtherSelection:
499 m_currentGroupSubMenuAction->setVisible(false);
500 break;
501 case GroupedButtonSelection:
502 m_currentGroupSubMenuAction->setText(tr("Button group '%1'").arg(buttonGroup->objectName()));
503 m_currentGroupSubMenuAction->setVisible(true);
504 break;
505 }
506
507 return m_taskActions + QDesignerTaskMenu::taskActions();
508}
509
510
511void ButtonTaskMenu::insertAction(int index, QAction *a)
512{
513 m_taskActions.insert(index, a);
514}
515
516/* Create a button list from the cursor selection */
517static ButtonList buttonList(const QDesignerFormWindowCursorInterface *cursor)
518{
519 ButtonList rc;
520 const int selectionCount = cursor->selectedWidgetCount();
521 for (int i = 0; i < selectionCount; i++) {
522 QAbstractButton *ab = qobject_cast<QAbstractButton *>(cursor->selectedWidget(i));
523 Q_ASSERT(ab);
524 rc += ab;
525 }
526 return rc;
527}
528
529// Create a command to remove the buttons from their group
530// If it would leave an empty or 1-member group behind, create a break command instead
531
532static QUndoCommand *createRemoveButtonsCommand(QDesignerFormWindowInterface *fw, const ButtonList &bl)
533{
534
535 QButtonGroup *bg = bl.constFirst()->group();
536 // Complete group or 1-member group?
537 if (bl.size() >= bg->buttons().size() - 1) {
539 if (!breakCmd->init(bg)) {
540 qWarning("** WARNING Failed to initialize BreakButtonGroupCommand!");
541 delete breakCmd;
542 return nullptr;
543 }
544 return breakCmd;
545 }
546 // Just remove the buttons
547
549 if (!removeCmd->init(bl)) {
550 qWarning("** WARNING Failed to initialize RemoveButtonsFromGroupCommand!");
551 delete removeCmd;
552 return nullptr;
553 }
554 return removeCmd;
555}
556
557void ButtonTaskMenu::createGroup()
558{
559 QDesignerFormWindowInterface *fw = formWindow();
560 const ButtonList bl = buttonList(fw->cursor());
561 // Do we need to remove the buttons from an existing group?
562 QUndoCommand *removeCmd = nullptr;
563 if (bl.constFirst()->group()) {
564 removeCmd = createRemoveButtonsCommand(fw, bl);
565 if (!removeCmd)
566 return;
567 }
568 // Add cmd
570 if (!addCmd->init(bl)) {
571 qWarning("** WARNING Failed to initialize CreateButtonGroupCommand!");
572 delete addCmd;
573 return;
574 }
575 // Need a macro [even if we only have the add command] since the command might trigger additional commands
576 QUndoStack *history = fw->commandHistory();
577 history->beginMacro(addCmd->text());
578 if (removeCmd)
579 history->push(removeCmd);
580 history->push(addCmd);
581 history->endMacro();
582}
583
585{
586 return qobject_cast<QAbstractButton *>(widget());
587}
588
589// Figure out if we have a homogenous selections (buttons of the same group or no group)
590ButtonTaskMenu::SelectionType ButtonTaskMenu::selectionType(const QDesignerFormWindowCursorInterface *cursor, QButtonGroup **ptrToGroup) const
591{
592 const int selectionCount = cursor->selectedWidgetCount();
593 if (!selectionCount)
594 return OtherSelection;
595
596 QButtonGroup *commonGroup = nullptr;
597 for (int i = 0; i < selectionCount; i++) {
598 if (const QAbstractButton *ab = qobject_cast<const QAbstractButton *>(cursor->selectedWidget(i))) {
599 QButtonGroup *buttonGroup = ab->group();
600 if (i) {
601 if (buttonGroup != commonGroup)
602 return OtherSelection;
603 } else {
604 commonGroup = buttonGroup;
605 }
606 } else {
607 return OtherSelection;
608 }
609 }
610
611 if (ptrToGroup)
612 *ptrToGroup = commonGroup;
613
614 return commonGroup ? GroupedButtonSelection : UngroupedButtonSelection;
615}
616
617void ButtonTaskMenu::addToGroup(QAction *a)
618{
620 Q_ASSERT(bg);
621
623 const ButtonList bl = buttonList(fw->cursor());
624 // Do we need to remove the buttons from an existing group?
625 QUndoCommand *removeCmd = nullptr;
626 if (bl.constFirst()->group()) {
628 if (!removeCmd)
629 return;
630 }
632 addCmd->init(bl, bg);
633
635 if (removeCmd) {
639 history->endMacro();
640 } else {
642 }
643}
644
645void ButtonTaskMenu::removeFromGroup()
646{
647 QDesignerFormWindowInterface *fw = formWindow();
648 if (QUndoCommand *cmd = createRemoveButtonsCommand(fw, buttonList(fw->cursor())))
649 fw->commandHistory()->push(cmd);
650}
651
652// -------------- CommandLinkButtonTaskMenu
653
654CommandLinkButtonTaskMenu::CommandLinkButtonTaskMenu(QCommandLinkButton *button, QObject *parent) :
655 ButtonTaskMenu(button, parent)
656{
657 TaskMenuInlineEditor *descriptonEditor = new LinkDescriptionTaskMenuInlineEditor(button, this);
658 QAction *descriptionAction = new QAction(tr("Change description..."), this);
659 connect(descriptionAction, &QAction::triggered, descriptonEditor, &TaskMenuInlineEditor::editText);
660 insertAction(1, descriptionAction);
661}
662
663}
664
665QT_END_NAMESPACE
void init(const ButtonList &bl, QButtonGroup *group)
void redo() override
Applies a change to the document.
void undo() override
Reverts a change to the document.
AddButtonsToGroupCommand(QDesignerFormWindowInterface *formWindow)
void undo() override
Reverts a change to the document.
void redo() override
Applies a change to the document.
BreakButtonGroupCommand(QDesignerFormWindowInterface *formWindow)
ButtonGroupCommand(const QString &description, QDesignerFormWindowInterface *formWindow)
static ButtonGroupList managedButtonGroups(const QDesignerFormWindowInterface *formWindow)
void initialize(const ButtonList &bl, QButtonGroup *buttonGroup)
static QString nameList(const ButtonList &bl)
void initialize(QDesignerFormWindowInterface *formWindow, QButtonGroup *buttonGroup=nullptr, QAbstractButton *currentButton=nullptr)
QAction * preferredEditAction() const override
QList< QAction * > taskActions() const override
QAction * preferredEditAction() const override
void insertAction(int index, QAction *a)
QList< QAction * > taskActions() const override
ButtonTextTaskMenuInlineEditor(QAbstractButton *button, QObject *parent)
void redo() override
Applies a change to the document.
CreateButtonGroupCommand(QDesignerFormWindowInterface *formWindow)
void undo() override
Reverts a change to the document.
LinkDescriptionTaskMenuInlineEditor(QAbstractButton *button, QObject *parent)
RemoveButtonsFromGroupCommand(QDesignerFormWindowInterface *formWindow)
void undo() override
Reverts a change to the document.
void redo() override
Applies a change to the document.
Auxiliary methods to store/retrieve settings.
static ButtonList buttonList(const QDesignerFormWindowCursorInterface *cursor)
static QUndoCommand * createRemoveButtonsCommand(QDesignerFormWindowInterface *fw, const ButtonList &bl)