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
signalsloteditorwindow.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
9
10#include <iconloader_p.h>
11#include <spacer_widget_p.h>
12#include <qlayout_widget_p.h>
13
14#include <QtDesigner/abstractformwindow.h>
15#include <QtDesigner/abstractformeditor.h>
16#include <QtDesigner/abstractformwindowmanager.h>
17#include <QtDesigner/qextensionmanager.h>
18#include <QtDesigner/abstractintegration.h>
19#include <QtDesigner/container.h>
20#include <QtDesigner/abstractmetadatabase.h>
21#include <QtDesigner/abstractformwindowcursor.h>
22#include <abstractdialoggui_p.h>
23
24#include <QtWidgets/qbuttongroup.h>
25#include <QtWidgets/qmenu.h>
26#include <QtWidgets/qcombobox.h>
27#include <QtWidgets/qapplication.h>
28#include <QtWidgets/qstyleditemdelegate.h>
29#include <QtWidgets/qitemeditorfactory.h>
30#include <QtWidgets/qtreeview.h>
31#include <QtWidgets/qheaderview.h>
32#include <QtWidgets/qboxlayout.h>
33#include <QtWidgets/qtoolbutton.h>
34#include <QtWidgets/qbuttongroup.h>
35#include <QtWidgets/qtoolbar.h>
36
37#include <QtGui/qaction.h>
38#include <QtGui/qstandarditemmodel.h>
39
40#include <QtCore/qabstractitemmodel.h>
41#include <QtCore/qdebug.h>
42#include <QtCore/qsortfilterproxymodel.h>
43
45
46using namespace Qt::StringLiterals;
47
48// Add suitable form widgets to a list of objects for the signal slot
49// editor. Prevent special widgets from showing up there.
50static void addWidgetToObjectList(const QWidget *w, QStringList &r)
51{
52 const QMetaObject *mo = w->metaObject();
53 if (mo != &QLayoutWidget::staticMetaObject && mo != &Spacer::staticMetaObject) {
54 const QString name = w->objectName().trimmed();
55 if (!name.isEmpty())
56 r.push_back(name);
57 }
58}
59
60static QStringList objectNameList(QDesignerFormWindowInterface *form)
61{
62 QStringList result;
63
64 QWidget *mainContainer = form->mainContainer();
65 if (!mainContainer)
66 return result;
67
68 // Add main container container pages (QStatusBar, QWizardPages) etc.
69 // to the list. Pages of containers on the form are not added, however.
70 if (const QDesignerContainerExtension *c = qt_extension<QDesignerContainerExtension *>(form->core()->extensionManager(), mainContainer)) {
71 const int count = c->count();
72 for (int i = 0 ; i < count; i++)
73 addWidgetToObjectList(c->widget(i), result);
74 }
75
76 const QDesignerFormWindowCursorInterface *cursor = form->cursor();
77 const int widgetCount = cursor->widgetCount();
78 for (int i = 0; i < widgetCount; ++i)
79 addWidgetToObjectList(cursor->widget(i), result);
80
81 const QDesignerMetaDataBaseInterface *mdb = form->core()->metaDataBase();
82
83 // Add managed actions and actions with managed menus
84 const auto actions = mainContainer->findChildren<QAction*>();
85 for (QAction *a : actions) {
86 if (!a->isSeparator()) {
87 if (QMenu *menu = a->menu()) {
88 if (mdb->item(menu))
89 result.push_back(menu->objectName());
90 } else {
91 if (mdb->item(a))
92 result.push_back(a->objectName());
93 }
94 }
95 }
96
97 // Add managed buttons groups
98 const auto buttonGroups = mainContainer->findChildren<QButtonGroup *>();
99 for (QButtonGroup * b : buttonGroups) {
100 if (mdb->item(b))
101 result.append(b->objectName());
102 }
103
104 result.sort();
105 return result;
106}
107
108namespace qdesigner_internal {
109
110// ------------ ConnectionModel
111
112ConnectionModel::ConnectionModel(QObject *parent) :
113 QAbstractItemModel(parent)
114{
115}
116
118{
119 if (m_editor == editor)
120 return;
121 beginResetModel();
122
123 if (m_editor) {
124 disconnect(m_editor.data(), &SignalSlotEditor::connectionAdded,
125 this, &ConnectionModel::connectionAdded);
126 disconnect(m_editor.data(), &SignalSlotEditor::connectionRemoved,
127 this, &ConnectionModel::connectionRemoved);
128 disconnect(m_editor.data(), &SignalSlotEditor::aboutToRemoveConnection,
129 this, &ConnectionModel::aboutToRemoveConnection);
130 disconnect(m_editor.data(), &SignalSlotEditor::aboutToAddConnection,
131 this, &ConnectionModel::aboutToAddConnection);
132 disconnect(m_editor.data(), &SignalSlotEditor::connectionChanged,
133 this, &ConnectionModel::connectionChanged);
134 }
135 m_editor = editor;
136 if (m_editor) {
137 connect(m_editor.data(), &SignalSlotEditor::connectionAdded,
138 this, &ConnectionModel::connectionAdded);
139 connect(m_editor.data(), &SignalSlotEditor::connectionRemoved,
140 this, &ConnectionModel::connectionRemoved);
141 connect(m_editor.data(), &SignalSlotEditor::aboutToRemoveConnection,
142 this, &ConnectionModel::aboutToRemoveConnection);
143 connect(m_editor.data(), &SignalSlotEditor::aboutToAddConnection,
144 this, &ConnectionModel::aboutToAddConnection);
145 connect(m_editor.data(), &SignalSlotEditor::connectionChanged,
146 this, &ConnectionModel::connectionChanged);
147 }
148 endResetModel();
149}
150
151QVariant ConnectionModel::headerData(int section, Qt::Orientation orientation,
152 int role) const
153{
154 if (orientation == Qt::Vertical || role != Qt::DisplayRole)
155 return QVariant();
156
157 static const QVariant senderTitle = tr("Sender");
158 static const QVariant signalTitle = tr("Signal");
159 static const QVariant receiverTitle = tr("Receiver");
160 static const QVariant slotTitle = tr("Slot");
161
162 switch (section) {
163 case 0:
164 return senderTitle;
165 case 1:
166 return signalTitle;
167 case 2:
168 return receiverTitle;
169 case 3:
170 return slotTitle;
171 }
172 return QVariant();
173}
174
175QModelIndex ConnectionModel::index(int row, int column,
176 const QModelIndex &parent) const
177{
178 if (parent.isValid() || !m_editor)
179 return QModelIndex();
180 if (row < 0 || row >= m_editor->connectionCount())
181 return QModelIndex();
182 return createIndex(row, column);
183}
184
185Connection *ConnectionModel::indexToConnection(const QModelIndex &index) const
186{
187 if (!index.isValid() || !m_editor)
188 return nullptr;
189 if (index.row() < 0 || index.row() >= m_editor->connectionCount())
190 return nullptr;
191 return m_editor->connection(index.row());
192}
193
195{
196 Q_ASSERT(m_editor);
197 return createIndex(m_editor->indexOfConnection(con), 0);
198}
199
201{
202 return QModelIndex();
203}
204
205int ConnectionModel::rowCount(const QModelIndex &parent) const
206{
207 if (parent.isValid() || !m_editor)
208 return 0;
209 return m_editor->connectionCount();
210}
211
212int ConnectionModel::columnCount(const QModelIndex &parent) const
213{
214 if (parent.isValid())
215 return 0;
216 return 4;
217}
218
219const SignalSlotConnection *ConnectionModel::connectionAt(const QModelIndex &index) const
220{
221 const int row = index.row();
222 return m_editor != nullptr && row >= 0 && row < m_editor->connectionCount()
223 ? static_cast<const SignalSlotConnection*>(m_editor->connection(row))
224 : nullptr;
225}
226
227QVariant ConnectionModel::data(const QModelIndex &index, int role) const
228{
229 enum { deprecatedMember = 0 };
230
231 const SignalSlotConnection *con = connectionAt(index);
232 if (con == nullptr)
233 return QVariant();
234
235 // Mark deprecated slots red/italic. Not currently in use (historically for Qt 3 slots in Qt 4),
236 // but may be used again in the future.
237 switch (role) {
238 case Qt::ForegroundRole:
239 return deprecatedMember ? QColor(Qt::red) : QVariant();
240 case Qt::FontRole:
241 if (deprecatedMember) {
242 QFont font = QApplication::font();
243 font.setItalic(true);
244 return font;
245 }
246 return QVariant();
247 case Qt::DisplayRole:
248 case Qt::EditRole:
249 return ConnectionModel::columnText(con, index.column());
250 default:
251 break;
252 }
253
254 return QVariant();
255}
256
257QString ConnectionModel::columnText(const SignalSlotConnection *con, int column)
258{
259 static const QString senderDefault = tr("<sender>");
260 static const QString signalDefault = tr("<signal>");
261 static const QString receiverDefault = tr("<receiver>");
262 static const QString slotDefault = tr("<slot>");
263
264 switch (column) {
265 case 0: {
266 const QString sender = con->sender();
267 return sender.isEmpty() ? senderDefault : sender;
268 }
269 case 1: {
270 const QString signalName = con->signal();
271 return signalName.isEmpty() ? signalDefault : signalName;
272 }
273 case 2: {
274 const QString receiver = con->receiver();
275 return receiver.isEmpty() ? receiverDefault : receiver;
276 }
277 case 3: {
278 const QString slotName = con->slot();
279 return slotName.isEmpty() ? slotDefault : slotName;
280 }
281 }
282 return QString();
283}
284
285bool ConnectionModel::setData(const QModelIndex &index, const QVariant &data, int)
286{
287 if (!index.isValid() || !m_editor)
288 return false;
289 if (data.metaType().id() != QMetaType::QString)
290 return false;
291
292 SignalSlotConnection *con = static_cast<SignalSlotConnection*>(m_editor->connection(index.row()));
293 QDesignerFormWindowInterface *form = m_editor->formWindow();
294
295 QString s = data.toString();
296 switch (index.column()) {
297 case 0:
298 if (!s.isEmpty() && !objectNameList(form).contains(s))
299 s.clear();
300 m_editor->setSource(con, s);
301 break;
302 case 1:
303 if (!memberFunctionListContains(form->core(), con->object(CETypes::EndPoint::Source), SignalMember, s))
304 s.clear();
305 m_editor->setSignal(con, s);
306 break;
307 case 2:
308 if (!s.isEmpty() && !objectNameList(form).contains(s))
309 s.clear();
310 m_editor->setTarget(con, s);
311 break;
312 case 3:
313 if (!memberFunctionListContains(form->core(), con->object(CETypes::EndPoint::Target), SlotMember, s))
314 s.clear();
315 m_editor->setSlot(con, s);
316 break;
317 }
318
319 return true;
320}
321
322void ConnectionModel::connectionAdded(Connection*)
323{
324 endInsertRows();
325}
326
327void ConnectionModel::connectionRemoved(int)
328{
329 endRemoveRows();
330}
331
332void ConnectionModel::aboutToRemoveConnection(Connection *con)
333{
334 Q_ASSERT(m_editor);
335 int idx = m_editor->indexOfConnection(con);
336 beginRemoveRows(QModelIndex(), idx, idx);
337}
338
339void ConnectionModel::aboutToAddConnection(int idx)
340{
341 Q_ASSERT(m_editor);
342 beginInsertRows(QModelIndex(), idx, idx);
343}
344
345Qt::ItemFlags ConnectionModel::flags(const QModelIndex&) const
346{
347 return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
348}
349
350void ConnectionModel::connectionChanged(Connection *con)
351{
352 Q_ASSERT(m_editor);
353 const int idx = m_editor->indexOfConnection(con);
354 SignalSlotConnection *changedCon = static_cast<SignalSlotConnection*>(m_editor->connection(idx));
355 SignalSlotConnection *c = nullptr;
356 for (int i=0; i<m_editor->connectionCount(); ++i) {
357 if (i == idx)
358 continue;
359 c = static_cast<SignalSlotConnection*>(m_editor->connection(i));
360 if (c->sender() == changedCon->sender() && c->signal() == changedCon->signal()
361 && c->receiver() == changedCon->receiver() && c->slot() == changedCon->slot()) {
362 const QString message = tr("The connection already exists!<br>%1").arg(changedCon->toString());
363 m_editor->formWindow()->core()->dialogGui()->message(m_editor->parentWidget(), QDesignerDialogGuiInterface::SignalSlotEditorMessage,
364 QMessageBox::Warning, tr("Signal and Slot Editor"), message, QMessageBox::Ok);
365 break;
366 }
367 }
368 emit dataChanged(createIndex(idx, 0), createIndex(idx, 3));
369}
370
372{
373 emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1));
374}
375}
376
377namespace {
378// ---------------------- InlineEditorModel
379
380class InlineEditorModel : public QStandardItemModel
381{
382 Q_OBJECT
383public:
384 enum { TitleItem = 1 };
385
386 InlineEditorModel(int rows, int cols, QObject *parent = nullptr);
387
388 void addTitle(const QString &title);
389 void addTextList(const QMap<QString, bool> &text_list);
390 void addText(const QString &text);
391 bool isTitle(int idx) const;
392
393 int findText(const QString &text) const;
394
395 Qt::ItemFlags flags(const QModelIndex &index) const override;
396};
397
398InlineEditorModel::InlineEditorModel(int rows, int cols, QObject *parent)
399 : QStandardItemModel(rows, cols, parent)
400{
401}
402
403void InlineEditorModel::addTitle(const QString &title)
404{
405 const int cnt = rowCount();
406 insertRows(cnt, 1);
407 QModelIndex cat_idx = index(cnt, 0);
408 setData(cat_idx, QString(title + u':'), Qt::DisplayRole);
409 setData(cat_idx, TitleItem, Qt::UserRole);
410 QFont font = QApplication::font();
411 font.setBold(true);
412 setData(cat_idx, font, Qt::FontRole);
413}
414
415bool InlineEditorModel::isTitle(int idx) const
416{
417 if (idx == -1)
418 return false;
419
420 return data(index(idx, 0), Qt::UserRole).toInt() == TitleItem;
421}
422
423void InlineEditorModel::addText(const QString &text)
424{
425 const int cnt = rowCount();
426 insertRows(cnt, 1);
427 setData(index(cnt, 0), text, Qt::DisplayRole);
428}
429
430void InlineEditorModel::addTextList(const QMap<QString, bool> &text_list)
431{
432 int cnt = rowCount();
433 insertRows(cnt, text_list.size());
434 QFont font = QApplication::font();
435 font.setItalic(true);
436 QVariant fontVariant = QVariant::fromValue(font);
437 for (auto it = text_list.cbegin(), itEnd = text_list.cend(); it != itEnd; ++it) {
438 const QModelIndex text_idx = index(cnt++, 0);
439 setData(text_idx, it.key(), Qt::DisplayRole);
440 if (it.value()) {
441 setData(text_idx, fontVariant, Qt::FontRole);
442 setData(text_idx, QColor(Qt::red), Qt::ForegroundRole);
443 }
444 }
445}
446
447Qt::ItemFlags InlineEditorModel::flags(const QModelIndex &index) const
448{
449 return isTitle(index.row())
450 ? Qt::ItemFlags(Qt::ItemIsEnabled)
451 : Qt::ItemFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
452}
453
454int InlineEditorModel::findText(const QString &text) const
455{
456 const int cnt = rowCount();
457 for (int i = 0; i < cnt; ++i) {
458 const QModelIndex idx = index(i, 0);
459 if (data(idx, Qt::UserRole).toInt() == TitleItem)
460 continue;
461 if (data(idx, Qt::DisplayRole).toString() == text)
462 return i;
463 }
464 return -1;
465}
466
467// ------------ InlineEditor
468class InlineEditor : public QComboBox
469{
470 Q_OBJECT
471 Q_PROPERTY(QString text READ text WRITE setText USER true)
472public:
473 InlineEditor(QWidget *parent = nullptr);
474
475 QString text() const;
476 void setText(const QString &text);
477
478 void addTitle(const QString &title);
479 void addText(const QString &text);
480 void addTextList(const QMap<QString, bool> &text_list);
481
482private slots:
483 void checkSelection(int idx);
484
485private:
486 InlineEditorModel *m_model;
487 int m_idx = -1;
488};
489
490InlineEditor::InlineEditor(QWidget *parent) :
491 QComboBox(parent)
492{
493 setModel(m_model = new InlineEditorModel(0, 4, this));
494 setFrame(false);
495 m_idx = -1;
496 connect(this, &QComboBox::activated,
497 this, &InlineEditor::checkSelection);
498}
499
500void InlineEditor::checkSelection(int idx)
501{
502 if (idx == m_idx)
503 return;
504
505 if (m_model->isTitle(idx))
506 setCurrentIndex(m_idx);
507 else
508 m_idx = idx;
509}
510
511void InlineEditor::addTitle(const QString &title)
512{
513 m_model->addTitle(title);
514}
515
516void InlineEditor::addTextList(const QMap<QString, bool> &text_list)
517{
518 m_model->addTextList(text_list);
519}
520
521void InlineEditor::addText(const QString &text)
522{
523 m_model->addText(text);
524}
525
526QString InlineEditor::text() const
527{
528 return currentText();
529}
530
531void InlineEditor::setText(const QString &text)
532{
533 m_idx = m_model->findText(text);
534 if (m_idx == -1)
535 m_idx = 0;
536 setCurrentIndex(m_idx);
537}
538
539// ------------------ ConnectionDelegate
540
541class ConnectionDelegate : public QStyledItemDelegate
542{
543 Q_OBJECT
544public:
545 ConnectionDelegate(QWidget *parent = nullptr);
546
547 void setForm(QDesignerFormWindowInterface *form);
548
549 QWidget *createEditor(QWidget *parent,
550 const QStyleOptionViewItem &option,
551 const QModelIndex &index) const override;
552
553private slots:
554 void emitCommitData();
555
556private:
557 QDesignerFormWindowInterface *m_form;
558};
559
560ConnectionDelegate::ConnectionDelegate(QWidget *parent)
561 : QStyledItemDelegate(parent)
562{
563 m_form = nullptr;
564
565 static QItemEditorFactory *factory = nullptr;
566 if (factory == nullptr) {
567 factory = new QItemEditorFactory;
568 QItemEditorCreatorBase *creator
569 = new QItemEditorCreator<InlineEditor>("text");
570 factory->registerEditor(QMetaType::QString, creator);
571 }
572
573 setItemEditorFactory(factory);
574}
575
576void ConnectionDelegate::setForm(QDesignerFormWindowInterface *form)
577{
578 m_form = form;
579}
580
581QWidget *ConnectionDelegate::createEditor(QWidget *parent,
582 const QStyleOptionViewItem &option,
583 const QModelIndex &index) const
584{
585 if (m_form == nullptr)
586 return nullptr;
587
588 QWidget *w = QStyledItemDelegate::createEditor(parent, option, index);
589 InlineEditor *inline_editor = qobject_cast<InlineEditor*>(w);
590 Q_ASSERT(inline_editor != nullptr);
591 const QAbstractItemModel *model = index.model();
592
593 const QModelIndex obj_name_idx = model->index(index.row(), index.column() <= 1 ? 0 : 2);
594 const QString obj_name = model->data(obj_name_idx, Qt::DisplayRole).toString();
595
596 switch (index.column()) {
597 case 0:
598 case 2: { // object names
599 const QStringList &obj_name_list = objectNameList(m_form);
600 QMap<QString, bool> markedNameList;
601 markedNameList.insert(tr("<object>"), false);
602 inline_editor->addTextList(markedNameList);
603 markedNameList.clear();
604 for (const QString &name : obj_name_list)
605 markedNameList.insert(name, false);
606 inline_editor->addTextList(markedNameList);
607 }
608 break;
609 case 1:
610 case 3: { // signals, slots
612 const QModelIndex peer_index = model->index(index.row(), type == qdesigner_internal::SignalMember ? 3 : 1);
613 const QString peer = model->data(peer_index, Qt::DisplayRole).toString();
614
615 const qdesigner_internal::ClassesMemberFunctions class_list = qdesigner_internal::reverseClassesMemberFunctions(obj_name, type, peer, m_form);
616
617 inline_editor->addText(type == qdesigner_internal::SignalMember ? tr("<signal>") : tr("<slot>"));
618 for (const qdesigner_internal::ClassMemberFunctions &classInfo : class_list) {
619 if (classInfo.m_className.isEmpty() || classInfo.m_memberList.isEmpty())
620 continue;
621 // Mark deprecated members by passing bool=true.
622 QMap<QString, bool> markedMemberList;
623 for (const QString &member : std::as_const(classInfo.m_memberList))
624 markedMemberList.insert(member, false);
625 inline_editor->addTitle(classInfo.m_className);
626 inline_editor->addTextList(markedMemberList);
627 }
628 }
629 break;
630 default:
631 break;
632 }
633
634 connect(inline_editor, &QComboBox::activated,
635 this, &ConnectionDelegate::emitCommitData);
636
637 return inline_editor;
638}
639
640void ConnectionDelegate::emitCommitData()
641{
642 InlineEditor *editor = qobject_cast<InlineEditor*>(sender());
643 emit commitData(editor);
644}
645
646}
647
648namespace qdesigner_internal {
649
650/*******************************************************************************
651** SignalSlotEditorWindow
652*/
653
654SignalSlotEditorWindow::SignalSlotEditorWindow(QDesignerFormEditorInterface *core,
655 QWidget *parent) :
656 QWidget(parent),
657 m_view(new QTreeView),
658 m_editor(nullptr),
659 m_add_button(new QToolButton),
660 m_remove_button(new QToolButton),
661 m_core(core),
662 m_model(new ConnectionModel(this)),
663 m_proxy_model(new QSortFilterProxyModel(this)),
664 m_handling_selection_change(false)
665{
666 m_proxy_model->setSourceModel(m_model);
667 m_view->setModel(m_proxy_model);
668 m_view->setSortingEnabled(true);
669 m_view->setItemDelegate(new ConnectionDelegate(this));
670 m_view->setEditTriggers(QAbstractItemView::DoubleClicked
671 | QAbstractItemView::EditKeyPressed);
672 m_view->setRootIsDecorated(false);
673 m_view->setTextElideMode (Qt::ElideMiddle);
674 connect(m_view->selectionModel(), &QItemSelectionModel::currentChanged,
675 this, &SignalSlotEditorWindow::updateUi);
676 connect(m_view->header(), &QHeaderView::sectionDoubleClicked,
677 m_view, &QTreeView::resizeColumnToContents);
678
679 QVBoxLayout *layout = new QVBoxLayout(this);
680 layout->setContentsMargins(QMargins());
681 layout->setSpacing(0);
682
683 QToolBar *toolBar = new QToolBar;
684 toolBar->setIconSize(QSize(22, 22));
685 m_add_button->setIcon(createIconSet("plus.png"_L1));
686 connect(m_add_button, &QAbstractButton::clicked, this, &SignalSlotEditorWindow::addConnection);
687 toolBar->addWidget(m_add_button);
688
689 m_remove_button->setIcon(createIconSet("minus.png"_L1));
690 connect(m_remove_button, &QAbstractButton::clicked, this, &SignalSlotEditorWindow::removeConnection);
691 toolBar->addWidget(m_remove_button);
692
693 layout->addWidget(toolBar);
694 layout->addWidget(m_view);
695
696 connect(core->formWindowManager(),
697 &QDesignerFormWindowManagerInterface::activeFormWindowChanged,
698 this, &SignalSlotEditorWindow::setActiveFormWindow);
699
700 updateUi();
701}
702
703void SignalSlotEditorWindow::setActiveFormWindow(QDesignerFormWindowInterface *form)
704{
705 QDesignerIntegrationInterface *integration = m_core->integration();
706
707 if (!m_editor.isNull()) {
708 disconnect(m_view->selectionModel(),
709 &QItemSelectionModel::currentChanged,
710 this, &SignalSlotEditorWindow::updateEditorSelection);
711 disconnect(m_editor.data(), &SignalSlotEditor::connectionSelected,
712 this, &SignalSlotEditorWindow::updateDialogSelection);
713 disconnect(m_editor.data(), &SignalSlotEditor::connectionAdded,
714 this, &SignalSlotEditorWindow::resizeColumns);
715 if (integration) {
716 disconnect(integration, &QDesignerIntegrationInterface::objectNameChanged,
717 this, &SignalSlotEditorWindow::objectNameChanged);
718 }
719 }
720
721 m_editor = form ? form->findChild<SignalSlotEditor*>() : nullptr;
722 m_model->setEditor(m_editor);
723 if (!m_editor.isNull()) {
724 ConnectionDelegate *delegate
725 = qobject_cast<ConnectionDelegate*>(m_view->itemDelegate());
726 if (delegate != nullptr)
727 delegate->setForm(form);
728
729 connect(m_view->selectionModel(),
730 &QItemSelectionModel::currentChanged,
731 this, &SignalSlotEditorWindow::updateEditorSelection);
732 connect(m_editor.data(), &SignalSlotEditor::connectionSelected,
733 this, &SignalSlotEditorWindow::updateDialogSelection);
734 connect(m_editor.data(), &SignalSlotEditor::connectionAdded,
735 this, &SignalSlotEditorWindow::resizeColumns);
736 if (integration) {
737 connect(integration, &QDesignerIntegrationInterface::objectNameChanged,
738 this, &SignalSlotEditorWindow::objectNameChanged);
739 }
740 }
741
742 resizeColumns();
743 updateUi();
744}
745
746void SignalSlotEditorWindow::updateDialogSelection(Connection *con)
747{
748 if (m_handling_selection_change || m_editor == nullptr)
749 return;
750
751 QModelIndex index = m_proxy_model->mapFromSource(m_model->connectionToIndex(con));
752 if (!index.isValid() || index == m_view->currentIndex())
753 return;
754 m_handling_selection_change = true;
755 m_view->scrollTo(index, QTreeView::EnsureVisible);
756 m_view->setCurrentIndex(index);
757 m_handling_selection_change = false;
758
759 updateUi();
760}
761
762void SignalSlotEditorWindow::updateEditorSelection(const QModelIndex &index)
763{
764 if (m_handling_selection_change || m_editor == nullptr)
765 return;
766
767 if (m_editor == nullptr)
768 return;
769
770 Connection *con = m_model->indexToConnection(m_proxy_model->mapToSource(index));
771 if (m_editor->selected(con))
772 return;
773 m_handling_selection_change = true;
774 m_editor->selectNone();
775 m_editor->setSelected(con, true);
776 m_handling_selection_change = false;
777
778 updateUi();
779}
780
781void SignalSlotEditorWindow::objectNameChanged(QDesignerFormWindowInterface *, QObject *, const QString &, const QString &)
782{
783 if (m_editor)
784 m_model->updateAll();
785}
786
787void SignalSlotEditorWindow::addConnection()
788{
789 if (m_editor.isNull())
790 return;
791
792 m_editor->addEmptyConnection();
793 updateUi();
794}
795
796void SignalSlotEditorWindow::removeConnection()
797{
798 if (m_editor.isNull())
799 return;
800
801 m_editor->deleteSelected();
802 updateUi();
803}
804
805void SignalSlotEditorWindow::updateUi()
806{
807 m_add_button->setEnabled(!m_editor.isNull());
808 m_remove_button->setEnabled(!m_editor.isNull() && m_view->currentIndex().isValid());
809}
810
811void SignalSlotEditorWindow::resizeColumns()
812{
813 for (int c = 0, count = m_model->columnCount(); c < count; ++c)
814 m_view->resizeColumnToContents(c);
815}
816
817} // namespace qdesigner_internal
818
819QT_END_NAMESPACE
820
821#include "signalsloteditorwindow.moc"
\inmodule QtCore
friend class QWidget
Definition qpainter.h:432
QModelIndex connectionToIndex(Connection *con) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Returns the data for the given role and section in the header with the specified orientation.
void setEditor(SignalSlotEditor *editor=nullptr)
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.
static void addWidgetToObjectList(const QWidget *w, QStringList &r)
static QStringList objectNameList(QDesignerFormWindowInterface *form)