11#include <QtDesigner/abstractformeditor.h>
12#include <QtDesigner/abstractformwindow.h>
13#include <QtDesigner/abstractpromotioninterface.h>
14#include <QtDesigner/abstractwidgetdatabase.h>
15#include <QtDesigner/abstractintegration.h>
16#include <abstractdialoggui_p.h>
18#include <QtWidgets/qboxlayout.h>
19#include <QtWidgets/qformlayout.h>
20#include <QtWidgets/qdialogbuttonbox.h>
21#include <QtWidgets/qtreeview.h>
22#include <QtWidgets/qheaderview.h>
23#include <QtWidgets/qpushbutton.h>
24#include <QtWidgets/qcombobox.h>
25#include <QtWidgets/qlineedit.h>
26#include <QtWidgets/qcheckbox.h>
27#include <QtWidgets/qlabel.h>
28#include <QtWidgets/qlayoutitem.h>
29#include <QtWidgets/qmenu.h>
31#include <QtGui/qaction.h>
32#include <QtGui/qvalidator.h>
34#include <QtCore/qitemselectionmodel.h>
35#include <QtCore/qtimer.h>
39using namespace Qt::StringLiterals;
51 int selectedBaseClass,
54 m_baseClassCombo(
new QComboBox),
55 m_classNameEdit(
new QLineEdit),
56 m_includeFileEdit(
new QLineEdit),
57 m_globalIncludeCheckBox(
new QCheckBox),
58 m_addButton(
new QPushButton(tr(
"Add")))
60 setTitle(tr(
"New Promoted Class"));
61 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
62 QHBoxLayout *hboxLayout =
new QHBoxLayout(
this);
64 m_classNameEdit->setValidator(
new QRegularExpressionValidator(QRegularExpression(u"^[_a-zA-Z:][:_a-zA-Z0-9]*$"_s), m_classNameEdit));
65 connect(m_classNameEdit, &QLineEdit::textChanged,
66 this, &NewPromotedClassPanel::slotNameChanged);
67 connect(m_includeFileEdit, &QLineEdit::textChanged,
68 this, &NewPromotedClassPanel::slotIncludeFileChanged);
70 m_baseClassCombo->setEditable(
false);
71 m_baseClassCombo->addItems(baseClasses);
72 if (selectedBaseClass != -1)
73 m_baseClassCombo->setCurrentIndex(selectedBaseClass);
76 QFormLayout *formLayout =
new QFormLayout();
77 formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
78 formLayout->addRow(tr(
"Base class name:"), m_baseClassCombo);
79 formLayout->addRow(tr(
"Promoted class name:"), m_classNameEdit);
81 QString toolTip = tr(
"Header file for C++ classes or module name for Qt for Python.");
82 auto *label =
new QLabel(tr(
"Header file:"));
83 label->setToolTip(toolTip);
84 formLayout->addRow(label, m_includeFileEdit);
85 m_includeFileEdit->setToolTip(toolTip);
87 toolTip = tr(
"Indicates that the header file is a global header file. Does not have any effect on Qt for Python.");
88 label =
new QLabel(tr(
"Global include"));
89 label->setToolTip(toolTip);
90 formLayout->addRow(label, m_globalIncludeCheckBox);
91 m_globalIncludeCheckBox->setToolTip(toolTip);
93 hboxLayout->addLayout(formLayout);
94 hboxLayout->addItem(
new QSpacerItem(15, 0, QSizePolicy::Fixed, QSizePolicy::Ignored));
96 QVBoxLayout *buttonLayout =
new QVBoxLayout();
98 m_addButton->setAutoDefault(
false);
100 m_addButton->setEnabled(
false);
101 buttonLayout->addWidget(m_addButton);
103 QPushButton *resetButton =
new QPushButton(tr(
"Reset"));
104 resetButton->setAutoDefault(
false);
107 buttonLayout->addWidget(resetButton);
108 buttonLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding));
109 hboxLayout->addLayout(buttonLayout);
116 emit newPromotedClass(promotionParameters(), &ok);
123 m_classNameEdit->setText(empty);
124 m_includeFileEdit->setText(empty);
125 m_globalIncludeCheckBox->setCheckState(Qt::Unchecked);
129 m_classNameEdit->setFocus(Qt::OtherFocusReason);
134 if (!className.isEmpty()) {
135 QString suggestedHeader = m_promotedHeaderLowerCase ?
136 className.toLower() : className;
137 suggestedHeader.replace(
"::"_L1,
"_"_L1);
138 if (!m_promotedHeaderSuffix.startsWith(u'.'))
139 suggestedHeader += u'.';
140 suggestedHeader += m_promotedHeaderSuffix;
142 const bool blocked = m_includeFileEdit->blockSignals(
true);
143 m_includeFileEdit->setText(suggestedHeader);
144 m_includeFileEdit->blockSignals(blocked);
154 const bool enabled = !m_classNameEdit->text().isEmpty() && !m_includeFileEdit->text().isEmpty();
155 m_addButton->setEnabled(enabled);
156 m_addButton->setDefault(enabled);
161 rc.m_baseClass = m_baseClassCombo->currentText();
162 rc.m_className = m_classNameEdit->text();
163 rc.m_includeFile = buildIncludeFile(m_includeFileEdit->text(),
164 m_globalIncludeCheckBox->checkState() == Qt::Checked ? IncludeGlobal : IncludeLocal);
169 const int index = m_baseClassCombo->findText (baseClass);
171 m_baseClassCombo->setCurrentIndex (index);
177 const QString &promotableWidgetClassName,
178 QString *promoteTo) :
184 m_promotion(core->promotion()),
187 m_buttonBox(
nullptr),
190 m_buttonBox = createButtonBox();
192 setWindowTitle(tr(
"Promoted Widgets"));
194 QVBoxLayout *vboxLayout =
new QVBoxLayout(
this);
197 QGroupBox *treeViewGroup =
new QGroupBox();
198 treeViewGroup->setTitle(tr(
"Promoted Classes"));
199 QVBoxLayout *treeViewVBoxLayout =
new QVBoxLayout(treeViewGroup);
201 m_treeView->setModel (m_model);
202 m_treeView->setMinimumWidth(450);
203 m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
205 connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged,
208 connect(m_treeView, &QWidget::customContextMenuRequested,
209 this, &QDesignerPromotionDialog::slotTreeViewContextMenu);
211 QHeaderView *headerView = m_treeView->header();
212 headerView->setSectionResizeMode(QHeaderView::ResizeToContents);
213 treeViewVBoxLayout->addWidget(m_treeView);
215 QHBoxLayout *hboxLayout =
new QHBoxLayout();
216 hboxLayout->addItem(
new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
218 m_removeButton->setAutoDefault(
false);
219 connect(m_removeButton, &QAbstractButton::clicked,
this, &QDesignerPromotionDialog::slotRemove);
220 m_removeButton->setEnabled(
false);
221 hboxLayout->addWidget(m_removeButton);
222 treeViewVBoxLayout->addLayout(hboxLayout);
223 vboxLayout->addWidget(treeViewGroup);
225 const QStringList &baseClassNameList = baseClassNames(m_promotion);
226 int preselectedBaseClass = -1;
227 if (m_mode == ModeEditChooseClass) {
228 preselectedBaseClass = baseClassNameList.indexOf(m_promotableWidgetClassName);
230 if (preselectedBaseClass == -1)
231 preselectedBaseClass = baseClassNameList.indexOf(
"QFrame"_L1);
234 newPromotedClassPanel->setPromotedHeaderSuffix(core->integration()->headerSuffix());
236 connect(newPromotedClassPanel, &NewPromotedClassPanel::newPromotedClass,
238 connect(
this, &QDesignerPromotionDialog::selectedBaseClassChanged,
239 newPromotedClassPanel, &NewPromotedClassPanel::chooseBaseClass);
240 vboxLayout->addWidget(newPromotedClassPanel);
242 vboxLayout->addWidget(m_buttonBox);
244 connect(m_model, &PromotionModel::includeFileChanged,
245 this, &QDesignerPromotionDialog::slotIncludeFileChanged);
247 connect(m_model, &PromotionModel::classNameChanged,
248 this, &QDesignerPromotionDialog::slotClassNameChanged);
251 if (m_mode == ModeEditChooseClass)
252 newPromotedClassPanel->grabFocus();
254 slotUpdateFromWidgetDatabase();
258 QDialogButtonBox *buttonBox =
new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Close);
260 connect(buttonBox, &QDialogButtonBox::accepted,
262 buttonBox->button(QDialogButtonBox::Ok)->setText(tr(
"Promote"));
263 buttonBox->button(QDialogButtonBox::Ok)->setEnabled(
false);
265 connect(buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject);
271 m_treeView->expandAll();
272 m_removeButton->setEnabled(
false);
276 QTimer::singleShot(0,
this, &QDesignerPromotionDialog::slotUpdateFromWidgetDatabase);
280 using WidgetDataBaseItemList = QList<QDesignerWidgetDataBaseItemInterface *>;
281 static QStringList rc;
284 const WidgetDataBaseItemList dbItems = promotion->promotionBaseClasses();
285 for (
auto *item : dbItems)
286 rc.append(item->name());
292 Q_ASSERT(m_mode == ModeEditChooseClass);
295 if (QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags)) {
296 if (flags & CanPromote) {
297 *m_promoteTo = dbItem ->name();
305 QDesignerWidgetDataBaseItemInterface *dbItem = databaseItemAt(m_treeView->selectionModel()->selection(), flags);
306 if (!dbItem || (flags & Referenced))
309 QString errorMessage;
310 if (m_promotion->removePromotedClass(dbItem->name(), &errorMessage)) {
311 slotUpdateFromWidgetDatabase();
313 displayError(errorMessage);
321 m_removeButton->setEnabled(dbItem && !(flags & Referenced));
323 if (m_mode == ModeEditChooseClass) {
324 const bool enablePromoted = flags & CanPromote;
325 m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enablePromoted);
326 m_buttonBox->button(QDialogButtonBox::Ok)->setDefault(enablePromoted);
330 const QString baseClass = dbItem->extends();
331 if (baseClass != m_lastSelectedBaseClass) {
332 m_lastSelectedBaseClass = baseClass;
333 emit selectedBaseClassChanged(m_lastSelectedBaseClass);
340 const QModelIndexList indexes = selected.indexes();
341 if (indexes.isEmpty())
343 const PromotionModel::ModelData data = m_model->modelData(indexes.constFirst());
344 QDesignerWidgetDataBaseItemInterface *dbItem = data.promotedItem;
350 if (m_mode == ModeEditChooseClass && dbItem && dbItem->isPromoted() && dbItem->extends() == m_promotableWidgetClassName)
358 QString errorMessage;
359 *ok = m_promotion->addPromotedClass(p.m_baseClass, p.m_className, p.m_includeFile, &errorMessage);
362 slotUpdateFromWidgetDatabase();
363 const QModelIndex newClassIndex = m_model->indexOfClass(p.m_className);
364 if (newClassIndex.isValid()) {
365 m_treeView->selectionModel()->select(newClassIndex, QItemSelectionModel::SelectCurrent|QItemSelectionModel::Rows);
368 displayError(errorMessage);
411 QAction *signalSlotAction = menu.addAction(tr(
"Change signals/slots..."));
412 connect(signalSlotAction, &QAction::triggered,
415 menu.exec(m_treeView->viewport()->mapToGlobal(pos));
424 SignalSlotDialog::editPromotedClass(m_core, dbItem->name(),
this);
428 m_core->dialogGui()->message(
this, QDesignerDialogGuiInterface::PromotionErrorMessage, QMessageBox::Warning,
429 tr(
"%1 - Error").arg(windowTitle()), message, QMessageBox::Close);
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.