1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Designer of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "connectdialog_p.h"
30#include "signalslot_utils_p.h"
31
32#include <signalslotdialog_p.h>
33#include <metadatabase_p.h>
34
35#include <QtDesigner/abstractformwindow.h>
36#include <QtDesigner/abstractformeditor.h>
37#include <QtDesigner/abstractwidgetdatabase.h>
38#include <QtDesigner/qextensionmanager.h>
39#include <QtDesigner/abstractlanguage.h>
40
41#include <QtWidgets/qpushbutton.h>
42
43QT_BEGIN_NAMESPACE
44
45static QString realClassName(QDesignerFormEditorInterface *core, QWidget *widget)
46{
47 QString class_name = QLatin1String(widget->metaObject()->className());
48 const QDesignerWidgetDataBaseInterface *wdb = core->widgetDataBase();
49 const int idx = wdb->indexOfObject(object: widget);
50 if (idx != -1)
51 class_name = wdb->item(index: idx)->name();
52 return class_name;
53}
54
55static QString widgetLabel(QDesignerFormEditorInterface *core, QWidget *widget)
56{
57 return QString::fromUtf8(str: "%1 (%2)")
58 .arg(args: qdesigner_internal::realObjectName(core, object: widget),
59 args: realClassName(core, widget));
60}
61
62namespace qdesigner_internal {
63
64ConnectDialog::ConnectDialog(QDesignerFormWindowInterface *formWindow,
65 QWidget *source, QWidget *destination,
66 QWidget *parent) :
67 QDialog(parent),
68 m_source(source),
69 m_destination(destination),
70 m_sourceMode(widgetMode(w: m_source, formWindow)),
71 m_destinationMode(widgetMode(w: m_destination, formWindow)),
72 m_formWindow(formWindow)
73{
74 m_ui.setupUi(this);
75
76 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
77
78 connect(sender: m_ui.signalList, signal: &QListWidget::itemClicked,
79 receiver: this, slot: &ConnectDialog::selectSignal);
80 connect(sender: m_ui.slotList, signal: &QListWidget::itemClicked,
81 receiver: this, slot: &ConnectDialog::selectSlot);
82 m_ui.slotList->setEnabled(false);
83
84 QPushButton *ok_button = okButton();
85 ok_button->setDefault(true);
86 ok_button->setEnabled(false);
87
88 connect(sender: m_ui.showAllCheckBox, signal: &QCheckBox::toggled, receiver: this, slot: &ConnectDialog::populateLists);
89
90 QDesignerFormEditorInterface *core = m_formWindow->core();
91 m_ui.signalGroupBox->setTitle(widgetLabel(core, widget: source));
92 m_ui.slotGroupBox->setTitle(widgetLabel(core, widget: destination));
93
94 m_ui.editSignalsButton->setEnabled(m_sourceMode != NormalWidget);
95 connect(sender: m_ui.editSignalsButton, signal: &QAbstractButton::clicked,
96 receiver: this, slot: &ConnectDialog::editSignals);
97
98 m_ui.editSlotsButton->setEnabled(m_destinationMode != NormalWidget);
99 connect(sender: m_ui.editSlotsButton, signal: &QAbstractButton::clicked,
100 receiver: this, slot: &ConnectDialog::editSlots);
101
102 populateLists();
103}
104
105ConnectDialog::WidgetMode ConnectDialog::widgetMode(QWidget *w, QDesignerFormWindowInterface *formWindow)
106{
107 QDesignerFormEditorInterface *core = formWindow->core();
108 if (qt_extension<QDesignerLanguageExtension*>(manager: core->extensionManager(), object: core))
109 return NormalWidget;
110
111 if (w == formWindow || formWindow->mainContainer() == w)
112 return MainContainer;
113
114 if (isPromoted(core: formWindow->core(), w))
115 return PromotedWidget;
116
117 return NormalWidget;
118}
119
120QPushButton *ConnectDialog::okButton()
121{
122 return m_ui.buttonBox->button(which: QDialogButtonBox::Ok);
123}
124
125void ConnectDialog::setOkButtonEnabled(bool e)
126{
127 okButton()->setEnabled(e);
128}
129
130void ConnectDialog::populateLists()
131{
132 populateSignalList();
133}
134
135void ConnectDialog::setSignalSlot(const QString &signal, const QString &slot)
136{
137 auto sigItems = m_ui.signalList->findItems(text: signal, flags: Qt::MatchExactly);
138
139 if (sigItems.isEmpty()) {
140 m_ui.showAllCheckBox->setChecked(true);
141 sigItems = m_ui.signalList->findItems(text: signal, flags: Qt::MatchExactly);
142 }
143
144 if (!sigItems.isEmpty()) {
145 selectSignal(item: sigItems.constFirst());
146 auto slotItems = m_ui.slotList->findItems(text: slot, flags: Qt::MatchExactly);
147 if (slotItems.isEmpty()) {
148 m_ui.showAllCheckBox->setChecked(true);
149 slotItems = m_ui.slotList->findItems(text: slot, flags: Qt::MatchExactly);
150 }
151 if (!slotItems.isEmpty())
152 selectSlot(item: slotItems.constFirst());
153 }
154}
155
156bool ConnectDialog::showAllSignalsSlots() const
157{
158 return m_ui.showAllCheckBox->isChecked();
159}
160
161void ConnectDialog::setShowAllSignalsSlots(bool showIt)
162{
163 m_ui.showAllCheckBox->setChecked(showIt);
164}
165
166void ConnectDialog::selectSignal(QListWidgetItem *item)
167{
168 if (item) {
169 m_ui.signalList->setCurrentItem(item);
170 populateSlotList(signal: item->text());
171 m_ui.slotList->setEnabled(true);
172 setOkButtonEnabled(!m_ui.slotList->selectedItems().isEmpty());
173 } else {
174 m_ui.signalList->clearSelection();
175 populateSlotList();
176 m_ui.slotList->setEnabled(false);
177 setOkButtonEnabled(false);
178 }
179}
180
181void ConnectDialog::selectSlot(QListWidgetItem *item)
182{
183 if (item) {
184 m_ui.slotList->setCurrentItem(item);
185 } else {
186 m_ui.slotList->clearSelection();
187 }
188 setOkButtonEnabled(true);
189}
190
191QString ConnectDialog::signal() const
192{
193 const auto item_list = m_ui.signalList->selectedItems();
194 if (item_list.size() != 1)
195 return QString();
196 return item_list.at(i: 0)->text();
197}
198
199QString ConnectDialog::slot() const
200{
201 const auto item_list = m_ui.slotList->selectedItems();
202 if (item_list.size() != 1)
203 return QString();
204 return item_list.at(i: 0)->text();
205}
206
207void ConnectDialog::populateSlotList(const QString &signal)
208{
209 enum { deprecatedSlot = 0 };
210 QString selectedName;
211 if (const QListWidgetItem * item = m_ui.slotList->currentItem())
212 selectedName = item->text();
213
214 m_ui.slotList->clear();
215
216 QMap<QString, QString> memberToClassName = getMatchingSlots(core: m_formWindow->core(), object: m_destination, signalSignature: signal, showAll: showAllSignalsSlots());
217
218 QFont font = QApplication::font();
219 font.setItalic(true);
220 QVariant variantFont = QVariant::fromValue(value: font);
221
222 QListWidgetItem *curr = nullptr;
223 QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin();
224 const QMap<QString, QString>::ConstIterator itMemberEnd = memberToClassName.constEnd();
225 while (itMember != itMemberEnd) {
226 const QString member = itMember.key();
227 QListWidgetItem *item = new QListWidgetItem(m_ui.slotList);
228 item->setText(member);
229 if (member == selectedName)
230 curr = item;
231
232 // Mark deprecated slots red. Not currently in use (historically for Qt 3 slots in Qt 4),
233 // but may be used again in the future.
234 if (deprecatedSlot) {
235 item->setData(role: Qt::FontRole, value: variantFont);
236 item->setData(role: Qt::ForegroundRole, value: QColor(Qt::red));
237 }
238 ++itMember;
239 }
240
241 if (curr)
242 m_ui.slotList->setCurrentItem(curr);
243
244 if (m_ui.slotList->selectedItems().isEmpty())
245 setOkButtonEnabled(false);
246}
247
248void ConnectDialog::populateSignalList()
249{
250 enum { deprecatedSignal = 0 };
251
252 QString selectedName;
253 if (const QListWidgetItem *item = m_ui.signalList->currentItem())
254 selectedName = item->text();
255
256 m_ui.signalList->clear();
257
258 QMap<QString, QString> memberToClassName = getSignals(core: m_formWindow->core(), object: m_source, showAll: showAllSignalsSlots());
259
260 QFont font = QApplication::font();
261 font.setItalic(true);
262 QVariant variantFont = QVariant::fromValue(value: font);
263
264 QListWidgetItem *curr = nullptr;
265 QMap<QString, QString>::ConstIterator itMember = memberToClassName.constBegin();
266 const QMap<QString, QString>::ConstIterator itMemberEnd = memberToClassName.constEnd();
267 while (itMember != itMemberEnd) {
268 const QString member = itMember.key();
269
270 QListWidgetItem *item = new QListWidgetItem(m_ui.signalList);
271 item->setText(member);
272 if (!selectedName.isEmpty() && member == selectedName)
273 curr = item;
274
275 // Mark deprecated signals red. Not currently in use (historically for Qt 3 slots in Qt 4),
276 // but may be used again in the future.
277 if (deprecatedSignal) {
278 item->setData(role: Qt::FontRole, value: variantFont);
279 item->setData(role: Qt::ForegroundRole, value: QColor(Qt::red));
280 }
281 ++itMember;
282 }
283
284 if (curr) {
285 m_ui.signalList->setCurrentItem(curr);
286 } else {
287 selectedName.clear();
288 }
289
290 populateSlotList(signal: selectedName);
291 if (!curr)
292 m_ui.slotList->setEnabled(false);
293}
294
295void ConnectDialog::editSignals()
296{
297 editSignalsSlots(w: m_source, mode: m_sourceMode, signalSlotDialogMode: SignalSlotDialog::FocusSignals);
298}
299
300void ConnectDialog::editSlots()
301{
302 editSignalsSlots(w: m_destination, mode: m_destinationMode, signalSlotDialogMode: SignalSlotDialog::FocusSlots);
303}
304
305void ConnectDialog::editSignalsSlots(QWidget *w, WidgetMode mode, int signalSlotDialogModeInt)
306{
307 const SignalSlotDialog::FocusMode signalSlotDialogMode = static_cast<SignalSlotDialog::FocusMode>(signalSlotDialogModeInt);
308 switch (mode) {
309 case NormalWidget:
310 break;
311 case MainContainer:
312 if (SignalSlotDialog::editMetaDataBase(fw: m_formWindow, object: w, parent: this, m: signalSlotDialogMode))
313 populateLists();
314 break;
315 case PromotedWidget:
316 if (SignalSlotDialog::editPromotedClass(core: m_formWindow->core(), baseObject: w, parent: this, m: signalSlotDialogMode))
317 populateLists();
318 break;
319 }
320}
321
322}
323
324QT_END_NAMESPACE
325

source code of qttools/src/designer/src/components/signalsloteditor/connectdialog.cpp