10#include <QtDesigner/abstractformeditor.h>
11#include <QtDesigner/abstractformwindow.h>
12#include <QtDesigner/abstractpromotioninterface.h>
13#include <QtDesigner/abstractwidgetdatabase.h>
14#include <QtDesigner/abstractintegration.h>
15#include <abstractdialoggui_p.h>
17#include <QtWidgets/qboxlayout.h>
18#include <QtWidgets/qformlayout.h>
19#include <QtWidgets/qdialogbuttonbox.h>
20#include <QtWidgets/qtreeview.h>
21#include <QtWidgets/qheaderview.h>
22#include <QtWidgets/qpushbutton.h>
23#include <QtWidgets/qcombobox.h>
24#include <QtWidgets/qlineedit.h>
25#include <QtWidgets/qcheckbox.h>
26#include <QtWidgets/qlabel.h>
27#include <QtWidgets/qlayoutitem.h>
28#include <QtWidgets/qmenu.h>
30#include <QtGui/qaction.h>
31#include <QtGui/qvalidator.h>
33#include <QtCore/qitemselectionmodel.h>
34#include <QtCore/qtimer.h>
38using namespace Qt::StringLiterals;
50 int selectedBaseClass,
53 m_baseClassCombo(
new QComboBox),
54 m_classNameEdit(
new QLineEdit),
55 m_includeFileEdit(
new QLineEdit),
56 m_globalIncludeCheckBox(
new QCheckBox),
57 m_addButton(
new QPushButton(tr(
"Add")))
59 setTitle(tr(
"New Promoted Class"));
60 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
61 QHBoxLayout *hboxLayout =
new QHBoxLayout(
this);
63 m_classNameEdit->setValidator(
new QRegularExpressionValidator(QRegularExpression(u"^[_a-zA-Z:][:_a-zA-Z0-9]*$"_s), m_classNameEdit));
64 connect(m_classNameEdit, &QLineEdit::textChanged,
65 this, &NewPromotedClassPanel::slotNameChanged);
66 connect(m_includeFileEdit, &QLineEdit::textChanged,
67 this, &NewPromotedClassPanel::slotIncludeFileChanged);
69 m_baseClassCombo->setEditable(
false);
70 m_baseClassCombo->addItems(baseClasses);
71 if (selectedBaseClass != -1)
72 m_baseClassCombo->setCurrentIndex(selectedBaseClass);
75 QFormLayout *formLayout =
new QFormLayout();
76 formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
77 formLayout->addRow(tr(
"Base class name:"), m_baseClassCombo);
78 formLayout->addRow(tr(
"Promoted class name:"), m_classNameEdit);
80 QString toolTip = tr(
"Header file for C++ classes or module name for Qt for Python.");
81 auto *label =
new QLabel(tr(
"Header file:"));
82 label->setToolTip(toolTip);
83 formLayout->addRow(label, m_includeFileEdit);
84 m_includeFileEdit->setToolTip(toolTip);
86 toolTip = tr(
"Indicates that the header file is a global header file. Does not have any effect on Qt for Python.");
87 label =
new QLabel(tr(
"Global include"));
88 label->setToolTip(toolTip);
89 formLayout->addRow(label, m_globalIncludeCheckBox);
90 m_globalIncludeCheckBox->setToolTip(toolTip);
92 hboxLayout->addLayout(formLayout);
93 hboxLayout->addItem(
new QSpacerItem(15, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
95 QVBoxLayout *buttonLayout =
new QVBoxLayout();
97 m_addButton->setAutoDefault(
false);
98 connect(m_addButton, &QAbstractButton::clicked,
this, &NewPromotedClassPanel::slotAdd);
99 m_addButton->setEnabled(
false);
100 buttonLayout->addWidget(m_addButton);
102 QPushButton *resetButton =
new QPushButton(tr(
"Reset"));
103 resetButton->setAutoDefault(
false);
104 connect(resetButton, &QAbstractButton::clicked,
this, &NewPromotedClassPanel::slotReset);
106 buttonLayout->addWidget(resetButton);
107 buttonLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding));
108 hboxLayout->addLayout(buttonLayout);
115 emit newPromotedClass(promotionParameters(), &ok);
122 m_classNameEdit->setText(empty);
123 m_includeFileEdit->setText(empty);
124 m_globalIncludeCheckBox->setCheckState(Qt::Unchecked);
128 m_classNameEdit->setFocus(Qt::OtherFocusReason);
133 if (!className.isEmpty()) {
134 QString suggestedHeader = m_promotedHeaderLowerCase ?
135 className.toLower() : className;
136 suggestedHeader.replace(
"::"_L1,
"_"_L1);
137 if (!m_promotedHeaderSuffix.startsWith(u'.'))
138 suggestedHeader += u'.';
139 suggestedHeader += m_promotedHeaderSuffix;
141 const bool blocked = m_includeFileEdit->blockSignals(
true);
142 m_includeFileEdit->setText(suggestedHeader);
143 m_includeFileEdit->blockSignals(blocked);
153 const bool enabled = !m_classNameEdit->text().isEmpty() && !m_includeFileEdit->text().isEmpty();
154 m_addButton->setEnabled(enabled);
155 m_addButton->setDefault(enabled);
160 rc.m_baseClass = m_baseClassCombo->currentText();
161 rc.m_className = m_classNameEdit->text();
162 rc.m_includeFile = buildIncludeFile(m_includeFileEdit->text(),
163 m_globalIncludeCheckBox->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal);
168 const int index = m_baseClassCombo->findText (baseClass);
170 m_baseClassCombo->setCurrentIndex (index);
176 const QString &promotableWidgetClassName,
177 QString *promoteTo) :
183 m_promotion(core->promotion()),
186 m_buttonBox(
nullptr),
189 m_buttonBox = createButtonBox();
191 setWindowTitle(tr(
"Promoted Widgets"));
193 QVBoxLayout *vboxLayout =
new QVBoxLayout(
this);
196 QGroupBox *treeViewGroup =
new QGroupBox();
197 treeViewGroup->setTitle(tr(
"Promoted Classes"));
198 QVBoxLayout *treeViewVBoxLayout =
new QVBoxLayout(treeViewGroup);
200 m_treeView->setModel (m_model);
201 m_treeView->setMinimumWidth(450);
202 m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
204 connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged,
205 this, &QDesignerPromotionDialog::slotSelectionChanged);
207 connect(m_treeView, &QWidget::customContextMenuRequested,
208 this, &QDesignerPromotionDialog::slotTreeViewContextMenu);
210 QHeaderView *headerView = m_treeView->header();
211 headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
212 treeViewVBoxLayout->addWidget(m_treeView);
214 QHBoxLayout *hboxLayout =
new QHBoxLayout();
215 hboxLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
217 m_removeButton->setAutoDefault(
false);
218 connect(m_removeButton, &QAbstractButton::clicked,
this, &QDesignerPromotionDialog::slotRemove);
219 m_removeButton->setEnabled(
false);
220 hboxLayout->addWidget(m_removeButton);
221 treeViewVBoxLayout->addLayout(hboxLayout);
222 vboxLayout->addWidget(treeViewGroup);
224 const QStringList &baseClassNameList = baseClassNames(m_promotion);
225 int preselectedBaseClass = -1;
226 if (m_mode == ModeEditChooseClass) {
227 preselectedBaseClass = baseClassNameList.indexOf(m_promotableWidgetClassName);
229 if (preselectedBaseClass == -1)
230 preselectedBaseClass = baseClassNameList.indexOf(
"QFrame"_L1);
233 newPromotedClassPanel->setPromotedHeaderSuffix(core->integration()->headerSuffix());
235 connect(newPromotedClassPanel, &NewPromotedClassPanel::newPromotedClass,
236 this, &QDesignerPromotionDialog::slotNewPromotedClass);
237 connect(
this, &QDesignerPromotionDialog::selectedBaseClassChanged,
238 newPromotedClassPanel, &NewPromotedClassPanel::chooseBaseClass);
239 vboxLayout->addWidget(newPromotedClassPanel);
241 vboxLayout->addWidget(m_buttonBox);
243 connect(m_model, &PromotionModel::includeFileChanged,
244 this, &QDesignerPromotionDialog::slotIncludeFileChanged);
246 connect(m_model, &PromotionModel::classNameChanged,
247 this, &QDesignerPromotionDialog::slotClassNameChanged);
250 if (m_mode == ModeEditChooseClass)
251 newPromotedClassPanel->grabFocus();
253 slotUpdateFromWidgetDatabase();
257 QDialogButtonBox *buttonBox =
new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Close);
259 connect(buttonBox, &QDialogButtonBox::accepted,
260 this, &QDesignerPromotionDialog::slotAcceptPromoteTo);
261 buttonBox->button(QDialogButtonBox::Ok)->setText(tr(
"Promote"));
262 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
false);
264 connect(buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject);
270 m_treeView->expandAll();
271 m_removeButton->setEnabled(
false);
275 QTimer::singleShot(0,
this, &QDesignerPromotionDialog::slotUpdateFromWidgetDatabase);
279 using WidgetDataBaseItemList = QList<QDesignerWidgetDataBaseItemInterface *>;
280 static QStringList rc;
283 const WidgetDataBaseItemList dbItems = promotion->promotionBaseClasses();
284 for (
auto *item : dbItems)
285 rc.append(item->name());
291 Q_ASSERT(m_mode == ModeEditChooseClass);
294 if (QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags)) {
295 if (flags & CanPromote) {
296 *m_promoteTo = dbItem ->name();
304 QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags);
305 if (!dbItem || (flags & Referenced))
308 QString errorMessage;
309 if (m_promotion->removePromotedClass(dbItem->name(), &errorMessage)) {
310 slotUpdateFromWidgetDatabase();
312 displayError(errorMessage);
320 m_removeButton->setEnabled(dbItem && !(flags & Referenced));
322 if (m_mode == ModeEditChooseClass) {
323 const bool enablePromoted = flags & CanPromote;
324 m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enablePromoted);
325 m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(enablePromoted);
329 const QString baseClass = dbItem->extends();
330 if (baseClass != m_lastSelectedBaseClass) {
331 m_lastSelectedBaseClass = baseClass;
332 emit selectedBaseClassChanged(m_lastSelectedBaseClass);
339 const QModelIndexList indexes = selected.indexes();
340 if (indexes.isEmpty())
342 const PromotionModel::ModelData data = m_model->modelData(indexes.constFirst());
343 QDesignerWidgetDataBaseItemInterface *dbItem = data.promotedItem;
349 if (m_mode == ModeEditChooseClass && dbItem && dbItem->isPromoted() && dbItem->extends() == m_promotableWidgetClassName)
357 QString errorMessage;
358 *ok = m_promotion->addPromotedClass(p.m_baseClass, p.m_className, p.m_includeFile, &errorMessage);
361 slotUpdateFromWidgetDatabase();
362 const QModelIndex newClassIndex = m_model->indexOfClass(p.m_className);
363 if (newClassIndex.isValid()) {
364 m_treeView->selectionModel()->select(newClassIndex, QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows);
367 displayError(errorMessage);
410 QAction *signalSlotAction = menu.addAction(tr(
"Change signals/slots..."));
411 connect(signalSlotAction, &QAction::triggered,
412 this, &QDesignerPromotionDialog::slotEditSignalsSlots);
414 menu.exec(m_treeView->viewport()->mapToGlobal(pos));
423 SignalSlotDialog::editPromotedClass(m_core, dbItem->name(),
this);
427 m_core->dialogGui()->message(
this, QDesignerDialogGuiInterface::PromotionErrorMessage, QMessageBox::Warning,
428 tr(
"%1 - Error").arg(windowTitle()), message, QMessageBox::Close);
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.