6#include <qdesigner_formwindowcommand_p.h>
7#include <formwindowbase_p.h>
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>
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>
23#include <QtGui/qaction.h>
24#include <QtGui/qactiongroup.h>
26#include <QtCore/qdebug.h>
28Q_DECLARE_METATYPE(QButtonGroup*)
32using namespace Qt::StringLiterals;
54 void initialize(
const ButtonList &bl, QButtonGroup *buttonGroup);
71 ButtonList m_buttonList;
72 QButtonGroup *m_buttonGroup;
84 m_buttonGroup = buttonGroup;
90 qDebug() <<
"Adding " << m_buttonList <<
" to " << m_buttonGroup;
91 for (
auto *b : std::as_const(m_buttonList))
92 m_buttonGroup->addButton(b);
98 qDebug() <<
"Removing " << m_buttonList <<
" from " << m_buttonGroup;
99 for (
auto *b : std::as_const(m_buttonList))
100 m_buttonGroup->removeButton(b);
106 qDebug() <<
"Creating " << m_buttonGroup <<
" from " << m_buttonList;
108 QDesignerFormWindowInterface *fw = formWindow();
109 QDesignerFormEditorInterface *core = fw->core();
110 core->metaDataBase()->add(m_buttonGroup);
113 core->objectInspector()->setFormWindow(fw);
119 qDebug() <<
"Removing " << m_buttonGroup <<
" consisting of " << m_buttonList;
121 QDesignerFormWindowInterface *fw = formWindow();
122 QDesignerFormEditorInterface *core = fw->core();
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);
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);
141 const QChar quote = QLatin1Char(
'\'');
142 const auto separator =
", "_L1;
143 for (qsizetype i = 0, size = bl.size(); i < size; ++i) {
147 rc += bl.at(i)->objectName();
154ButtonGroupList
ButtonGroupCommand::managedButtonGroups(
const QDesignerFormWindowInterface *formWindow)
156 const QDesignerMetaDataBaseInterface *mdb = formWindow->core()->metaDataBase();
159 for (
auto *o : formWindow->mainContainer()->children()) {
160 if (!o->isWidgetType()) {
161 if (QButtonGroup *bg = qobject_cast<QButtonGroup *>(o)) {
176 bool init(
const ButtonList &bl);
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);
203 bool init(QButtonGroup *group);
218 initialize(group->buttons(), group);
219 setText(QApplication::translate(
"Command",
"Break button group '%1'").arg(group->objectName()));
229 void init(
const ButtonList &bl, QButtonGroup *group);
242 initialize(bl, group);
244 setText(QApplication::translate(
"Command",
"Add '%1' to '%2'").arg(nameList(bl), group->objectName()));
251 bool init(
const ButtonList &bl);
266 QButtonGroup *group = bl.constFirst()->group();
269 if (bl.size() >= group->buttons().size())
271 initialize(bl, group);
273 setText(QApplication::translate(
"Command",
"Remove '%1' from '%2'").arg(nameList(bl), group->objectName()));
280 m_selectGroupAction(
new QAction(tr(
"Select members"),
this)),
281 m_breakGroupAction(
new QAction(tr(
"Break"),
this))
283 connect(m_breakGroupAction, &QAction::triggered,
this, &ButtonGroupMenu::breakGroup);
284 connect(m_selectGroupAction, &QAction::triggered,
this, &ButtonGroupMenu::selectGroup);
289 m_buttonGroup = buttonGroup;
290 m_currentButton = currentButton;
291 m_formWindow = formWindow;
292 Q_ASSERT(m_formWindow);
294 const bool canBreak = buttonGroup !=
nullptr;
295 m_breakGroupAction->setEnabled(canBreak);
296 m_selectGroupAction->setEnabled(canBreak);
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);
309 m_formWindow->selectWidget(m_currentButton,
true);
315 if (cmd->init(m_buttonGroup)) {
317 QUndoStack *history = m_formWindow->commandHistory();
318 history->beginMacro(cmd->text());
322 qWarning(
"** WARNING Failed to initialize BreakButtonGroupCommand!");
330 m_buttonGroup(buttonGroup)
332 m_taskActions.push_back(m_menu.breakGroupAction());
333 m_taskActions.push_back(m_menu.selectGroupAction());
338 return m_menu.selectGroupAction();
343 m_menu.initialize(QDesignerFormWindowInterface::findFormWindow(m_buttonGroup), m_buttonGroup);
344 return m_taskActions;
364 QWidget *w = widget();
365 QStyleOptionButton opt;
367 return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
387 QWidget *w = widget();
388 QStyleOptionButton opt;
390 return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
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))
406 connect(m_createGroupAction, &QAction::triggered,
this, &ButtonTaskMenu::createGroup);
408 connect(m_preferredEditAction, &QAction::triggered, textEditor, &TaskMenuInlineEditor::editText);
409 connect(m_removeFromGroupAction, &QAction::triggered,
this, &ButtonTaskMenu::removeFromGroup);
411 m_assignToGroupSubMenuAction->setMenu(m_assignGroupSubMenu);
413 m_currentGroupSubMenu->addAction(m_groupMenu.breakGroupAction());
414 m_currentGroupSubMenu->addAction(m_groupMenu.selectGroupAction());
415 m_currentGroupSubMenuAction->setMenu(m_currentGroupSubMenu);
418 m_taskActions.append(m_preferredEditAction);
419 m_taskActions.append(m_assignToGroupSubMenuAction);
420 m_taskActions.append(m_currentGroupSubMenuAction);
421 m_taskActions.append(createSeparator());
426 delete m_assignGroupSubMenu;
427 delete m_currentGroupSubMenu;
432 return m_preferredEditAction;
435bool ButtonTaskMenu::refreshAssignMenu(
const QDesignerFormWindowInterface *fw,
int buttonCount, SelectionType st, QButtonGroup *currentGroup)
438 if (m_assignActionGroup) {
439 delete m_assignActionGroup;
440 m_assignActionGroup =
nullptr;
442 m_assignGroupSubMenu->clear();
443 if (st == OtherSelection)
448 const bool canAssignToNewGroup = buttonCount > 1;
449 m_createGroupAction->setEnabled(canAssignToNewGroup);
450 if (canAssignToNewGroup)
451 m_assignGroupSubMenu->addAction(m_createGroupAction);
454 const ButtonGroupList bl = ButtonGroupCommand::managedButtonGroups(fw);
456 const auto groupCount = bl.size();
457 const bool hasAddGroups = groupCount > 1 || (groupCount == 1 && !bl.contains(currentGroup));
459 if (!m_assignGroupSubMenu->isEmpty())
460 m_assignGroupSubMenu->addSeparator();
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);
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);
481 return !m_assignGroupSubMenu->isEmpty();
487 QButtonGroup *buttonGroup =
nullptr;
489 QDesignerFormWindowInterface *fw = formWindow();
490 const SelectionType st = selectionType(fw->cursor(), &buttonGroup);
492 m_groupMenu.initialize(fw, buttonGroup, button());
493 const bool hasAssignOptions = ncThis->refreshAssignMenu(fw, fw->cursor()->selectedWidgetCount(), st, buttonGroup);
494 m_assignToGroupSubMenuAction->setVisible(hasAssignOptions);
497 case UngroupedButtonSelection:
499 m_currentGroupSubMenuAction->setVisible(
false);
501 case GroupedButtonSelection:
502 m_currentGroupSubMenuAction->setText(tr(
"Button group '%1'").arg(buttonGroup->objectName()));
503 m_currentGroupSubMenuAction->setVisible(
true);
507 return m_taskActions + QDesignerTaskMenu::taskActions();
513 m_taskActions.insert(index, a);
520 const int selectionCount = cursor->selectedWidgetCount();
521 for (
int i = 0; i < selectionCount; i++) {
522 QAbstractButton *ab = qobject_cast<QAbstractButton *>(cursor->selectedWidget(i));
535 QButtonGroup *bg = bl.constFirst()->group();
537 if (bl.size() >= bg->buttons().size() - 1) {
539 if (!breakCmd->init(bg)) {
540 qWarning(
"** WARNING Failed to initialize BreakButtonGroupCommand!");
549 if (!removeCmd->init(bl)) {
550 qWarning(
"** WARNING Failed to initialize RemoveButtonsFromGroupCommand!");
559 QDesignerFormWindowInterface *fw = formWindow();
560 const ButtonList bl = buttonList(fw->cursor());
562 QUndoCommand *removeCmd =
nullptr;
563 if (bl.constFirst()->group()) {
564 removeCmd = createRemoveButtonsCommand(fw, bl);
570 if (!addCmd->init(bl)) {
571 qWarning(
"** WARNING Failed to initialize CreateButtonGroupCommand!");
576 QUndoStack *history = fw->commandHistory();
577 history->beginMacro(addCmd->text());
579 history->push(removeCmd);
580 history->push(addCmd);
586 return qobject_cast<QAbstractButton *>(widget());
590ButtonTaskMenu::SelectionType
ButtonTaskMenu::selectionType(
const QDesignerFormWindowCursorInterface *cursor, QButtonGroup **ptrToGroup)
const
592 const int selectionCount = cursor->selectedWidgetCount();
594 return OtherSelection;
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();
601 if (buttonGroup != commonGroup)
602 return OtherSelection;
604 commonGroup = buttonGroup;
607 return OtherSelection;
612 *ptrToGroup = commonGroup;
614 return commonGroup ? GroupedButtonSelection : UngroupedButtonSelection;
647 QDesignerFormWindowInterface *fw = formWindow();
648 if (QUndoCommand *cmd = createRemoveButtonsCommand(fw, buttonList(fw->cursor())))
649 fw->commandHistory()->push(cmd);
658 QAction *descriptionAction =
new QAction(tr(
"Change description..."),
this);
659 connect(descriptionAction, &QAction::triggered, descriptonEditor, &TaskMenuInlineEditor::editText);
660 insertAction(1, descriptionAction);
Auxiliary methods to store/retrieve settings.
static ButtonList buttonList(const QDesignerFormWindowCursorInterface *cursor)
static QUndoCommand * createRemoveButtonsCommand(QDesignerFormWindowInterface *fw, const ButtonList &bl)