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