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 | |
43 | QT_BEGIN_NAMESPACE |
44 | |
45 | static 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 | |
55 | static 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 | |
62 | namespace qdesigner_internal { |
63 | |
64 | ConnectDialog::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 | |
105 | ConnectDialog::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 | |
120 | QPushButton *ConnectDialog::okButton() |
121 | { |
122 | return m_ui.buttonBox->button(which: QDialogButtonBox::Ok); |
123 | } |
124 | |
125 | void ConnectDialog::setOkButtonEnabled(bool e) |
126 | { |
127 | okButton()->setEnabled(e); |
128 | } |
129 | |
130 | void ConnectDialog::populateLists() |
131 | { |
132 | populateSignalList(); |
133 | } |
134 | |
135 | void 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 | |
156 | bool ConnectDialog::showAllSignalsSlots() const |
157 | { |
158 | return m_ui.showAllCheckBox->isChecked(); |
159 | } |
160 | |
161 | void ConnectDialog::setShowAllSignalsSlots(bool showIt) |
162 | { |
163 | m_ui.showAllCheckBox->setChecked(showIt); |
164 | } |
165 | |
166 | void 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 | |
181 | void 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 | |
191 | QString 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 | |
199 | QString 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 | |
207 | void 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 | |
248 | void 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 | |
295 | void ConnectDialog::editSignals() |
296 | { |
297 | editSignalsSlots(w: m_source, mode: m_sourceMode, signalSlotDialogMode: SignalSlotDialog::FocusSignals); |
298 | } |
299 | |
300 | void ConnectDialog::editSlots() |
301 | { |
302 | editSignalsSlots(w: m_destination, mode: m_destinationMode, signalSlotDialogMode: SignalSlotDialog::FocusSlots); |
303 | } |
304 | |
305 | void 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 | |
324 | QT_END_NAMESPACE |
325 | |