1
/****************************************************************************
3
** Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
5
** This file is part of the designer application of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include <QtCore/QAbstractItemModel>
30
#include <QtCore/QDebug>
31
#include <QtGui/QStandardItemModel>
32
#include <QtGui/QComboBox>
33
#include <QtGui/QApplication>
34
#include <QtGui/QItemDelegate>
35
#include <QtGui/QItemEditorFactory>
36
#include <QtGui/QTreeView>
37
#include <QtGui/QVBoxLayout>
38
#include <QtGui/QToolButton>
40
#include <iconloader_p.h>
42
#include <abstractformeditor.h>
43
#include <abstractformwindowmanager.h>
44
#include "signalsloteditorwindow.h"
45
#include "signalsloteditor_p.h"
46
#include "signalsloteditor.h"
48
namespace qdesigner_internal {
50
/*******************************************************************************
54
ConnectionModel::ConnectionModel(SignalSlotEditor *editor, QObject *parent)
55
: QAbstractItemModel(parent)
59
connect(m_editor, SIGNAL(connectionAdded(Connection*)),
60
this, SLOT(connectionAdded(Connection*)));
61
connect(m_editor, SIGNAL(connectionRemoved(int)),
62
this, SLOT(connectionRemoved(int)));
63
connect(m_editor, SIGNAL(aboutToRemoveConnection(Connection*)),
64
this, SLOT(aboutToRemoveConnection(Connection*)));
65
connect(m_editor, SIGNAL(aboutToAddConnection(int)),
66
this, SLOT(aboutToAddConnection(int)));
67
connect(m_editor, SIGNAL(connectionChanged(Connection*)),
68
this, SLOT(connectionChanged(Connection*)));
71
QVariant ConnectionModel::headerData(int section, Qt::Orientation orientation,
76
if (orientation == Qt::Vertical)
78
if (role != Qt::DisplayRole)
83
result = tr("Sender");
86
result = tr("Signal");
89
result = tr("Receiver");
99
QModelIndex ConnectionModel::index(int row, int column,
100
const QModelIndex &parent) const
102
if (parent.isValid())
103
return QModelIndex();
104
if (row < 0 || row >= m_editor->connectionCount())
105
return QModelIndex();
106
return createIndex(row, column);
109
Connection *ConnectionModel::indexToConnection(const QModelIndex &index) const
111
if (!index.isValid())
113
if (index.row() < 0 || index.row() >= m_editor->connectionCount())
115
return m_editor->connection(index.row());
118
QModelIndex ConnectionModel::connectionToIndex(Connection *con) const
120
return createIndex(m_editor->indexOfConnection(con), 0);
123
QModelIndex ConnectionModel::parent(const QModelIndex&) const
125
return QModelIndex();
128
int ConnectionModel::rowCount(const QModelIndex &parent) const
130
if (parent.isValid())
132
return m_editor->connectionCount();
135
int ConnectionModel::columnCount(const QModelIndex &parent) const
137
if (parent.isValid())
142
QVariant ConnectionModel::data(const QModelIndex &index, int role) const
144
if (role != Qt::DisplayRole && role != Qt::EditRole)
147
if (index.row() < 0 || index.row() >= m_editor->connectionCount())
150
SignalSlotConnection *con
151
= static_cast<SignalSlotConnection*>(m_editor->connection(index.row()));
154
switch (index.column()) {
156
QString sender = con->sender();
157
if (sender.isEmpty())
158
sender = tr("<sender>");
162
QString signal = con->signal();
163
if (signal.isEmpty())
164
signal = tr("<signal>");
168
QString receiver = con->receiver();
169
if (receiver.isEmpty())
170
receiver = tr("<receiver>");
174
QString slot = con->slot();
184
bool ConnectionModel::setData(const QModelIndex &index, const QVariant &data, int)
186
if (!index.isValid())
188
if (data.type() != QVariant::String)
191
SignalSlotConnection *con = static_cast<SignalSlotConnection*>(m_editor->connection(index.row()));
192
QDesignerFormWindowInterface *form = m_editor->formWindow();
194
QString s = data.toString();
195
switch (index.column()) {
197
if (!s.isEmpty() && !objectNameList(form).contains(s))
199
m_editor->setSource(con, s);
203
if (!memberList(form, con->widget(CETypes::EndPoint::Source), SignalMember).contains(s))
205
m_editor->setSignal(con, s);
209
if (!s.isEmpty() && !objectNameList(form).contains(s))
211
m_editor->setTarget(con, s);
215
if (!memberList(form, con->widget(CETypes::EndPoint::Target), SlotMember).contains(s))
217
m_editor->setSlot(con, s);
225
void ConnectionModel::connectionAdded(Connection*)
230
void ConnectionModel::connectionRemoved(int)
235
void ConnectionModel::aboutToRemoveConnection(Connection *con)
237
int idx = m_editor->indexOfConnection(con);
238
beginRemoveRows(QModelIndex(), idx, idx);
241
void ConnectionModel::aboutToAddConnection(int idx)
243
beginInsertRows(QModelIndex(), idx, idx);
246
Qt::ItemFlags ConnectionModel::flags(const QModelIndex&) const
248
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
251
void ConnectionModel::connectionChanged(Connection *con)
253
int idx = m_editor->indexOfConnection(con);
254
emit dataChanged(createIndex(idx, 0), createIndex(idx, 3));
257
/*******************************************************************************
263
class InlineEditorModel : public QStandardItemModel
267
InlineEditorModel(int rows, int cols, QObject *parent = 0);
269
void addTitle(const QString &title);
270
void addTextList(const QStringList &text_list);
271
void addText(const QString &text);
272
bool isTitle(int idx) const;
274
int findText(const QString &text) const;
276
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
279
class InlineEditor : public QComboBox
282
Q_PROPERTY(QString text READ text WRITE setText)
284
InlineEditor(QWidget *parent = 0);
287
QString text() const;
288
void setText(const QString &text);
290
void addTitle(const QString &title);
291
void addText(const QString &text);
292
void addTextList(const QStringList &text_list);
295
void checkSelection(int idx);
298
InlineEditorModel *m_model;
302
InlineEditorModel::InlineEditorModel(int rows, int cols, QObject *parent)
303
: QStandardItemModel(rows, cols, parent)
307
void InlineEditorModel::addTitle(const QString &title)
309
int cnt = rowCount();
311
QModelIndex cat_idx = index(cnt, 0);
312
setData(cat_idx, title + QLatin1Char(':'), Qt::DisplayRole);
313
setData(cat_idx, TITLE_ITEM, Qt::UserRole);
314
QFont font = QApplication::font();
316
setData(cat_idx, font, Qt::FontRole);
319
bool InlineEditorModel::isTitle(int idx) const
324
return data(index(idx, 0), Qt::UserRole).toInt() == TITLE_ITEM;
327
void InlineEditorModel::addText(const QString &text)
329
int cnt = rowCount();
331
setData(index(cnt, 0), text, Qt::DisplayRole);
334
void InlineEditorModel::addTextList(const QStringList &text_list)
336
int cnt = rowCount();
337
insertRows(cnt, text_list.size());
338
foreach (QString text, text_list) {
339
QModelIndex text_idx = index(cnt++, 0);
340
setData(text_idx, text, Qt::DisplayRole);
344
Qt::ItemFlags InlineEditorModel::flags(const QModelIndex &index) const
346
if (isTitle(index.row()))
347
return Qt::ItemIsEnabled;
349
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
352
int InlineEditorModel::findText(const QString &text) const
354
int cnt = rowCount();
355
for (int i = 0; i < cnt; ++i) {
356
QModelIndex idx = index(i, 0);
357
if (data(idx, Qt::UserRole).toInt() == TITLE_ITEM)
359
if (data(idx, Qt::DisplayRole).toString() == text)
365
InlineEditor::InlineEditor(QWidget *parent)
368
setModel(m_model = new InlineEditorModel(0, 4, this));
371
connect(this, SIGNAL(activated(int)), this, SLOT(checkSelection(int)));
374
InlineEditor::~InlineEditor()
378
void InlineEditor::checkSelection(int idx)
382
if (m_model->isTitle(idx))
383
setCurrentIndex(m_idx);
388
void InlineEditor::addTitle(const QString &title)
390
m_model->addTitle(title);
393
void InlineEditor::addTextList(const QStringList &text_list)
395
m_model->addTextList(text_list);
398
void InlineEditor::addText(const QString &text)
400
m_model->addText(text);
403
QString InlineEditor::text() const
405
return currentText();
408
void InlineEditor::setText(const QString &text)
410
m_idx = m_model->findText(text);
413
setCurrentIndex(m_idx);
416
/*******************************************************************************
417
** ConnectionDelegate
420
class ConnectionDelegate : public QItemDelegate
424
ConnectionDelegate(QWidget *parent = 0);
426
void setForm(QDesignerFormWindowInterface *form);
428
virtual QWidget *createEditor(QWidget *parent,
429
const QStyleOptionViewItem &option,
430
const QModelIndex &index) const;
433
void emitCommitData();
436
QDesignerFormWindowInterface *m_form;
439
ConnectionDelegate::ConnectionDelegate(QWidget *parent)
440
: QItemDelegate(parent)
444
static QItemEditorFactory *factory = 0;
446
factory = new QItemEditorFactory;
447
QItemEditorCreatorBase *creator
448
= new QItemEditorCreator<InlineEditor>("text");
449
factory->registerEditor(QVariant::String, creator);
452
setItemEditorFactory(factory);
455
void ConnectionDelegate::setForm(QDesignerFormWindowInterface *form)
460
QWidget *ConnectionDelegate::createEditor(QWidget *parent,
461
const QStyleOptionViewItem &option,
462
const QModelIndex &index) const
467
QWidget *w = QItemDelegate::createEditor(parent, option, index);
468
InlineEditor *inline_editor = qobject_cast<InlineEditor*>(w);
469
Q_ASSERT(inline_editor != 0);
470
const QAbstractItemModel *model = index.model();
472
QModelIndex obj_name_idx = model->index(index.row(), index.column() <= 1 ? 0 : 2);
473
QString obj_name = model->data(obj_name_idx, Qt::DisplayRole).toString();
475
if (index.column() == 0 || index.column() == 2) { // object names
476
QStringList obj_name_list = objectNameList(m_form);
477
obj_name_list.prepend(tr("<object>"));
478
inline_editor->addTextList(obj_name_list);
479
} else { // signals, slots
480
MemberType type = index.column() == 1 ? SignalMember : SlotMember;
481
QModelIndex peer_index = model->index(index.row(), type == SignalMember ? 3 : 1);
482
QString peer = model->data(peer_index, Qt::DisplayRole).toString();
483
ClassList class_list = classList(obj_name, type, peer, m_form);
485
inline_editor->addText(type == SignalMember ? tr("<signal>") : tr("<slot>"));
486
foreach (const ClassInfo &class_info, class_list) {
487
if (class_info.class_name.isEmpty() || class_info.member_list.isEmpty())
489
inline_editor->addTitle(class_info.class_name);
490
inline_editor->addTextList(class_info.member_list);
494
connect(inline_editor, SIGNAL(activated(int)), this, SLOT(emitCommitData()));
496
return inline_editor;
499
void ConnectionDelegate::emitCommitData()
501
InlineEditor *editor = qobject_cast<InlineEditor*>(sender());
502
emit commitData(editor);
505
/*******************************************************************************
506
** SignalSlotEditorWindow
509
SignalSlotEditorWindow::SignalSlotEditorWindow(QDesignerFormEditorInterface *core,
513
m_handling_selection_change = false;
516
m_view = new QTreeView(this);
517
m_view->setItemDelegate(new ConnectionDelegate(this));
518
m_view->setEditTriggers(QAbstractItemView::SelectedClicked
519
| QAbstractItemView::EditKeyPressed);
520
m_view->setRootIsDecorated(false);
521
connect(m_view, SIGNAL(activated(const QModelIndex&)), this, SLOT(updateUi()));
523
QVBoxLayout *layout = new QVBoxLayout(this);
524
layout->setMargin(0);
525
layout->addWidget(m_view);
527
QHBoxLayout *layout2 = new QHBoxLayout;
528
layout2->setMargin(3);
529
layout->addLayout(layout2);
530
layout2->addStretch();
532
m_remove_button = new QToolButton(this);
533
m_remove_button->setIcon(createIconSet(QLatin1String("minus.png")));
534
connect(m_remove_button, SIGNAL(clicked()), this, SLOT(removeConnection()));
535
layout2->addWidget(m_remove_button);
537
m_add_button = new QToolButton(this);
538
m_add_button->setIcon(createIconSet(QLatin1String("plus.png")));
539
connect(m_add_button, SIGNAL(clicked()), this, SLOT(addConnection()));
540
layout2->addWidget(m_add_button);
542
connect(core->formWindowManager(),
543
SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)),
544
this, SLOT(setActiveFormWindow(QDesignerFormWindowInterface*)));
549
void SignalSlotEditorWindow::setActiveFormWindow(QDesignerFormWindowInterface *form)
553
if (!m_editor.isNull()) {
554
disconnect(m_view->selectionModel(),
555
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
556
this, SLOT(updateEditorSelection(const QModelIndex&)));
557
disconnect(m_editor, SIGNAL(connectionSelected(Connection*)),
558
this, SLOT(updateDialogSelection(Connection*)));
561
m_editor = qFindChild<SignalSlotEditor*>(form);
563
if (!m_editor.isNull()) {
564
m_view->setModel(m_editor->model());
565
ConnectionDelegate *delegate
566
= qobject_cast<ConnectionDelegate*>(m_view->itemDelegate());
568
delegate->setForm(form);
570
connect(m_view->selectionModel(),
571
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
572
this, SLOT(updateEditorSelection(const QModelIndex&)));
573
connect(m_editor, SIGNAL(connectionSelected(Connection*)),
574
this, SLOT(updateDialogSelection(Connection*)));
580
void SignalSlotEditorWindow::updateDialogSelection(Connection *con)
582
if (m_handling_selection_change || m_editor == 0)
585
ConnectionModel *model = qobject_cast<ConnectionModel*>(m_editor->model());
586
Q_ASSERT(model != 0);
587
QModelIndex index = model->connectionToIndex(con);
588
if (index == m_view->currentIndex())
590
m_handling_selection_change = true;
591
m_view->setCurrentIndex(index);
592
m_handling_selection_change = false;
597
void SignalSlotEditorWindow::updateEditorSelection(const QModelIndex &index)
599
if (m_handling_selection_change || m_editor == 0)
605
ConnectionModel *model = qobject_cast<ConnectionModel*>(m_editor->model());
606
Q_ASSERT(model != 0);
607
Connection *con = model->indexToConnection(index);
608
if (m_editor->selected(con))
610
m_handling_selection_change = true;
611
m_editor->selectNone();
612
m_editor->setSelected(con, true);
613
m_handling_selection_change = false;
618
void SignalSlotEditorWindow::addConnection()
620
if (m_editor.isNull())
623
m_editor->addEmptyConnection();
627
void SignalSlotEditorWindow::removeConnection()
629
if (m_editor.isNull())
632
m_editor->deleteSelected();
636
void SignalSlotEditorWindow::updateUi()
638
m_add_button->setEnabled(!m_editor.isNull());
639
m_remove_button->setEnabled(!m_editor.isNull() && m_view->currentIndex().isValid());
642
} // namespace qdesigner_internal
644
#include "signalsloteditorwindow.moc"