7#include <qdesigner_formwindowcommand_p.h>
8#include <formwindowbase_p.h>
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>
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>
24#include <QtGui/qaction.h>
25#include <QtGui/qactiongroup.h>
27#include <QtCore/qdebug.h>
29Q_DECLARE_METATYPE(QButtonGroup*)
33using namespace Qt::StringLiterals;
55 void initialize(
const ButtonList &bl, QButtonGroup *buttonGroup);
72 ButtonList m_buttonList;
73 QButtonGroup *m_buttonGroup;
85 m_buttonGroup = buttonGroup;
91 qDebug() <<
"Adding " << m_buttonList <<
" to " << m_buttonGroup;
92 for (
auto *b : std::as_const(m_buttonList))
93 m_buttonGroup->addButton(b);
99 qDebug() <<
"Removing " << m_buttonList <<
" from " << m_buttonGroup;
100 for (
auto *b : std::as_const(m_buttonList))
101 m_buttonGroup->removeButton(b);
107 qDebug() <<
"Creating " << m_buttonGroup <<
" from " << m_buttonList;
109 QDesignerFormWindowInterface *fw = formWindow();
110 QDesignerFormEditorInterface *core = fw->core();
111 core->metaDataBase()->add(m_buttonGroup);
114 core->objectInspector()->setFormWindow(fw);
120 qDebug() <<
"Removing " << m_buttonGroup <<
" consisting of " << m_buttonList;
122 QDesignerFormWindowInterface *fw = formWindow();
123 QDesignerFormEditorInterface *core = fw->core();
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);
134 fwb->emitObjectRemoved(m_buttonGroup);
135 core->metaDataBase()->remove(m_buttonGroup);
136 core->objectInspector()->setFormWindow(fw);
142 const QChar quote = QLatin1Char(
'\'');
143 const auto separator =
", "_L1;
144 for (qsizetype i = 0, size = bl.size(); i < size; ++i) {
148 rc += bl.at(i)->objectName();
155ButtonGroupList
ButtonGroupCommand::managedButtonGroups(
const QDesignerFormWindowInterface *formWindow)
157 const QDesignerMetaDataBaseInterface *mdb = formWindow->core()->metaDataBase();
160 for (
auto *o : formWindow->mainContainer()->children()) {
161 if (!o->isWidgetType()) {
162 if (QButtonGroup *bg = qobject_cast<QButtonGroup *>(o)) {
177 bool init(
const ButtonList &bl);
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);
204 bool init(QButtonGroup *group);
219 initialize(group->buttons(), group);
220 setText(QApplication::translate(
"Command",
"Break button group '%1'").arg(group->objectName()));
230 void init(
const ButtonList &bl, QButtonGroup *group);
243 initialize(bl, group);
245 setText(QApplication::translate(
"Command",
"Add '%1' to '%2'").arg(nameList(bl), group->objectName()));
252 bool init(
const ButtonList &bl);
267 QButtonGroup *group = bl.constFirst()->group();
270 if (bl.size() >= group->buttons().size())
272 initialize(bl, group);
274 setText(QApplication::translate(
"Command",
"Remove '%1' from '%2'").arg(nameList(bl), group->objectName()));
281 m_selectGroupAction(
new QAction(tr(
"Select members"),
this)),
282 m_breakGroupAction(
new QAction(tr(
"Break"),
this))
284 connect(m_breakGroupAction, &QAction::triggered,
this, &
ButtonGroupMenu::breakGroup);
285 connect(m_selectGroupAction, &QAction::triggered,
this, &ButtonGroupMenu::selectGroup);
290 m_buttonGroup = buttonGroup;
291 m_currentButton = currentButton;
292 m_formWindow = formWindow;
293 Q_ASSERT(m_formWindow);
295 const bool canBreak = buttonGroup !=
nullptr;
296 m_breakGroupAction->setEnabled(canBreak);
297 m_selectGroupAction->setEnabled(canBreak);
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);
310 m_formWindow->selectWidget(m_currentButton,
true);
316 if (cmd->init(m_buttonGroup)) {
318 QUndoStack *history = m_formWindow->commandHistory();
319 history->beginMacro(cmd->text());
323 qWarning(
"** WARNING Failed to initialize BreakButtonGroupCommand!");
331 m_buttonGroup(buttonGroup)
333 m_taskActions.push_back(m_menu.breakGroupAction());
334 m_taskActions.push_back(m_menu.selectGroupAction());
339 return m_menu.selectGroupAction();
344 m_menu.initialize(QDesignerFormWindowInterface::findFormWindow(m_buttonGroup), m_buttonGroup);
345 return m_taskActions;
365 QWidget *w = widget();
366 QStyleOptionButton opt;
368 return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
388 QWidget *w = widget();
389 QStyleOptionButton opt;
391 return w->style()->subElementRect(QStyle::SE_PushButtonContents, &opt, w);
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))
407 connect(m_createGroupAction, &QAction::triggered,
this, &ButtonTaskMenu::createGroup);
409 connect(m_preferredEditAction, &QAction::triggered, textEditor, &TaskMenuInlineEditor::editText);
410 connect(m_removeFromGroupAction, &QAction::triggered,
this, &
ButtonTaskMenu::removeFromGroup);
412 m_assignToGroupSubMenuAction->setMenu(m_assignGroupSubMenu);
414 m_currentGroupSubMenu->addAction(m_groupMenu.breakGroupAction());
415 m_currentGroupSubMenu->addAction(m_groupMenu.selectGroupAction());
416 m_currentGroupSubMenuAction->setMenu(m_currentGroupSubMenu);
419 m_taskActions.append(m_preferredEditAction);
420 m_taskActions.append(m_assignToGroupSubMenuAction);
421 m_taskActions.append(m_currentGroupSubMenuAction);
422 m_taskActions.append(createSeparator());
427 delete m_assignGroupSubMenu;
428 delete m_currentGroupSubMenu;
433 return m_preferredEditAction;
436bool ButtonTaskMenu::refreshAssignMenu(
const QDesignerFormWindowInterface *fw,
int buttonCount, SelectionType st, QButtonGroup *currentGroup)
439 if (m_assignActionGroup) {
440 delete m_assignActionGroup;
441 m_assignActionGroup =
nullptr;
443 m_assignGroupSubMenu->clear();
444 if (st == OtherSelection)
449 const bool canAssignToNewGroup = buttonCount > 1;
450 m_createGroupAction->setEnabled(canAssignToNewGroup);
451 if (canAssignToNewGroup)
452 m_assignGroupSubMenu->addAction(m_createGroupAction);
455 const ButtonGroupList bl = ButtonGroupCommand::managedButtonGroups(fw);
457 const auto groupCount = bl.size();
458 const bool hasAddGroups = groupCount > 1 || (groupCount == 1 && !bl.contains(currentGroup));
460 if (!m_assignGroupSubMenu->isEmpty())
461 m_assignGroupSubMenu->addSeparator();
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);
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);
482 return !m_assignGroupSubMenu->isEmpty();
488 QButtonGroup *buttonGroup =
nullptr;
490 QDesignerFormWindowInterface *fw = formWindow();
491 const SelectionType st = selectionType(fw->cursor(), &buttonGroup);
493 m_groupMenu.initialize(fw, buttonGroup, button());
494 const bool hasAssignOptions = ncThis->refreshAssignMenu(fw, fw->cursor()->selectedWidgetCount(), st, buttonGroup);
495 m_assignToGroupSubMenuAction->setVisible(hasAssignOptions);
498 case UngroupedButtonSelection:
500 m_currentGroupSubMenuAction->setVisible(
false);
502 case GroupedButtonSelection:
503 m_currentGroupSubMenuAction->setText(tr(
"Button group '%1'").arg(buttonGroup->objectName()));
504 m_currentGroupSubMenuAction->setVisible(
true);
508 return m_taskActions + QDesignerTaskMenu::taskActions();
514 m_taskActions.insert(index, a);
521 const int selectionCount = cursor->selectedWidgetCount();
522 for (
int i = 0; i < selectionCount; i++) {
523 QAbstractButton *ab = qobject_cast<QAbstractButton *>(cursor->selectedWidget(i));
536 QButtonGroup *bg = bl.constFirst()->group();
538 if (bl.size() >= bg->buttons().size() - 1) {
540 if (!breakCmd->init(bg)) {
541 qWarning(
"** WARNING Failed to initialize BreakButtonGroupCommand!");
550 if (!removeCmd->init(bl)) {
551 qWarning(
"** WARNING Failed to initialize RemoveButtonsFromGroupCommand!");
560 QDesignerFormWindowInterface *fw = formWindow();
561 const ButtonList bl = buttonList(fw->cursor());
563 QUndoCommand *removeCmd =
nullptr;
564 if (bl.constFirst()->group()) {
565 removeCmd = createRemoveButtonsCommand(fw, bl);
571 if (!addCmd->init(bl)) {
572 qWarning(
"** WARNING Failed to initialize CreateButtonGroupCommand!");
577 QUndoStack *history = fw->commandHistory();
578 history->beginMacro(addCmd->text());
580 history->push(removeCmd);
581 history->push(addCmd);
587 return qobject_cast<QAbstractButton *>(widget());
591ButtonTaskMenu::SelectionType
ButtonTaskMenu::selectionType(
const QDesignerFormWindowCursorInterface *cursor, QButtonGroup **ptrToGroup)
const
593 const int selectionCount = cursor->selectedWidgetCount();
595 return OtherSelection;
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();
602 if (buttonGroup != commonGroup)
603 return OtherSelection;
605 commonGroup = buttonGroup;
608 return OtherSelection;
613 *ptrToGroup = commonGroup;
615 return commonGroup ? GroupedButtonSelection : UngroupedButtonSelection;
648 QDesignerFormWindowInterface *fw = formWindow();
649 if (QUndoCommand *cmd = createRemoveButtonsCommand(fw, buttonList(fw->cursor())))
650 fw->commandHistory()->push(cmd);
659 QAction *descriptionAction =
new QAction(tr(
"Change description..."),
this);
660 connect(descriptionAction, &QAction::triggered, descriptonEditor, &TaskMenuInlineEditor::editText);
661 insertAction(1, descriptionAction);
Auxiliary methods to store/retrieve settings.
static ButtonList buttonList(const QDesignerFormWindowCursorInterface *cursor)
static QUndoCommand * createRemoveButtonsCommand(QDesignerFormWindowInterface *fw, const ButtonList &bl)