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
realClassName(QDesignerFormEditorInterface * core,QWidget * widget)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(widget);
50 if (idx != -1)
51 class_name = wdb->item(idx)->name();
52 return class_name;
53 }
54
widgetLabel(QDesignerFormEditorInterface * core,QWidget * widget)55 static QString widgetLabel(QDesignerFormEditorInterface *core, QWidget *widget)
56 {
57 return QString::fromUtf8("%1 (%2)")
58 .arg(qdesigner_internal::realObjectName(core, widget),
59 realClassName(core, widget));
60 }
61
62 namespace qdesigner_internal {
63
ConnectDialog(QDesignerFormWindowInterface * formWindow,QWidget * source,QWidget * destination,QWidget * parent)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(m_source, formWindow)),
71 m_destinationMode(widgetMode(m_destination, formWindow)),
72 m_formWindow(formWindow)
73 {
74 m_ui.setupUi(this);
75
76 setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
77
78 connect(m_ui.signalList, &QListWidget::itemClicked,
79 this, &ConnectDialog::selectSignal);
80 connect(m_ui.slotList, &QListWidget::itemClicked,
81 this, &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(m_ui.showAllCheckBox, &QCheckBox::toggled, this, &ConnectDialog::populateLists);
89
90 QDesignerFormEditorInterface *core = m_formWindow->core();
91 m_ui.signalGroupBox->setTitle(widgetLabel(core, source));
92 m_ui.slotGroupBox->setTitle(widgetLabel(core, destination));
93
94 m_ui.editSignalsButton->setEnabled(m_sourceMode != NormalWidget);
95 connect(m_ui.editSignalsButton, &QAbstractButton::clicked,
96 this, &ConnectDialog::editSignals);
97
98 m_ui.editSlotsButton->setEnabled(m_destinationMode != NormalWidget);
99 connect(m_ui.editSlotsButton, &QAbstractButton::clicked,
100 this, &ConnectDialog::editSlots);
101
102 populateLists();
103 }
104
widgetMode(QWidget * w,QDesignerFormWindowInterface * formWindow)105 ConnectDialog::WidgetMode ConnectDialog::widgetMode(QWidget *w, QDesignerFormWindowInterface *formWindow)
106 {
107 QDesignerFormEditorInterface *core = formWindow->core();
108 if (qt_extension<QDesignerLanguageExtension*>(core->extensionManager(), core))
109 return NormalWidget;
110
111 if (w == formWindow || formWindow->mainContainer() == w)
112 return MainContainer;
113
114 if (isPromoted(formWindow->core(), w))
115 return PromotedWidget;
116
117 return NormalWidget;
118 }
119
okButton()120 QPushButton *ConnectDialog::okButton()
121 {
122 return m_ui.buttonBox->button(QDialogButtonBox::Ok);
123 }
124
setOkButtonEnabled(bool e)125 void ConnectDialog::setOkButtonEnabled(bool e)
126 {
127 okButton()->setEnabled(e);
128 }
129
populateLists()130 void ConnectDialog::populateLists()
131 {
132 populateSignalList();
133 }
134
setSignalSlot(const QString & signal,const QString & slot)135 void ConnectDialog::setSignalSlot(const QString &signal, const QString &slot)
136 {
137 auto sigItems = m_ui.signalList->findItems(signal, Qt::MatchExactly);
138
139 if (sigItems.isEmpty()) {
140 m_ui.showAllCheckBox->setChecked(true);
141 sigItems = m_ui.signalList->findItems(signal, Qt::MatchExactly);
142 }
143
144 if (!sigItems.isEmpty()) {
145 selectSignal(sigItems.constFirst());
146 auto slotItems = m_ui.slotList->findItems(slot, Qt::MatchExactly);
147 if (slotItems.isEmpty()) {
148 m_ui.showAllCheckBox->setChecked(true);
149 slotItems = m_ui.slotList->findItems(slot, Qt::MatchExactly);
150 }
151 if (!slotItems.isEmpty())
152 selectSlot(slotItems.constFirst());
153 }
154 }
155
showAllSignalsSlots() const156 bool ConnectDialog::showAllSignalsSlots() const
157 {
158 return m_ui.showAllCheckBox->isChecked();
159 }
160
setShowAllSignalsSlots(bool showIt)161 void ConnectDialog::setShowAllSignalsSlots(bool showIt)
162 {
163 m_ui.showAllCheckBox->setChecked(showIt);
164 }
165
selectSignal(QListWidgetItem * item)166 void ConnectDialog::selectSignal(QListWidgetItem *item)
167 {
168 if (item) {
169 m_ui.signalList->setCurrentItem(item);
170 populateSlotList(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
selectSlot(QListWidgetItem * item)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
signal() const191 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(0)->text();
197 }
198
slot() const199 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(0)->text();
205 }
206
populateSlotList(const QString & signal)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(m_formWindow->core(), m_destination, signal, showAllSignalsSlots());
217
218 QFont font = QApplication::font();
219 font.setItalic(true);
220 QVariant variantFont = QVariant::fromValue(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(Qt::FontRole, variantFont);
236 item->setData(Qt::ForegroundRole, 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
populateSignalList()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(m_formWindow->core(), m_source, showAllSignalsSlots());
259
260 QFont font = QApplication::font();
261 font.setItalic(true);
262 QVariant variantFont = QVariant::fromValue(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(Qt::FontRole, variantFont);
279 item->setData(Qt::ForegroundRole, 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(selectedName);
291 if (!curr)
292 m_ui.slotList->setEnabled(false);
293 }
294
editSignals()295 void ConnectDialog::editSignals()
296 {
297 editSignalsSlots(m_source, m_sourceMode, SignalSlotDialog::FocusSignals);
298 }
299
editSlots()300 void ConnectDialog::editSlots()
301 {
302 editSignalsSlots(m_destination, m_destinationMode, SignalSlotDialog::FocusSlots);
303 }
304
editSignalsSlots(QWidget * w,WidgetMode mode,int signalSlotDialogModeInt)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(m_formWindow, w, this, signalSlotDialogMode))
313 populateLists();
314 break;
315 case PromotedWidget:
316 if (SignalSlotDialog::editPromotedClass(m_formWindow->core(), w, this, signalSlotDialogMode))
317 populateLists();
318 break;
319 }
320 }
321
322 }
323
324 QT_END_NAMESPACE
325