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