1
/* This file is part of the KDE project
2
Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3
Copyright (C) 2004-2009 Jarosław Staniek <staniek@kde.org>
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Library General Public
7
License as published by the Free Software Foundation; either
8
version 2 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Library General Public License for more details.
15
You should have received a copy of the GNU Library General Public License
16
along with this library; see the file COPYING.LIB. If not, write to
17
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
21
#include "connectiondialog.h"
26
#include <qmetaobject.h>
28
#include <kpushbutton.h>
29
#include <kiconloader.h>
30
#include <kmessagebox.h>
34
#include "kexitableview.h"
35
#include "kexitableviewdata.h"
39
//#include "formmanager.h"
40
#include "objecttree.h"
43
using namespace KFormDesigner;
45
/////////////////////////////////////////////////////////////////////////////////
46
///////////// The dialog to edit or add/remove connections //////////////////////
47
/////////////////////////////////////////////////////////////////////////////////
48
ConnectionDialog::ConnectionDialog(Form *form, QWidget *parent)
53
setObjectName("connections_dialog");
55
setWindowTitle(i18n("Edit Form Connections"));
56
setButtons(KDialog::Ok | KDialog::Cancel | KDialog::Details);
57
setDefaultButton(KDialog::Ok);
59
QFrame *frame = new QFrame(this);
61
QHBoxLayout *layout = new QHBoxLayout(frame);
63
// Setup the details widget /////////
64
QWidget *details = new QWidget(frame);
65
layout->addWidget(details);
66
QHBoxLayout *detailsLyr = new QHBoxLayout(details);
67
setDetailsWidget(details);
68
setDetailsWidgetVisible(true);
70
m_pixmapLabel = new QLabel(details);
71
detailsLyr->addWidget(m_pixmapLabel);
72
m_pixmapLabel->setFixedWidth(int(IconSize(KIconLoader::Desktop) * 1.5));
73
m_pixmapLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
75
m_textLabel = new QLabel(details);
76
detailsLyr->addWidget(m_textLabel);
77
m_textLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
80
// And the KexiTableView ////////
81
m_data = new KexiTableViewData();
82
m_table = new KexiTableView(0, frame, "connections_tableview");
83
m_table->setSpreadSheetMode();
84
m_table->setInsertingEnabled(true);
86
m_table->setData(m_data, false);
87
m_table->adjustColumnWidthToContents(0);
88
layout->addWidget(m_table);
90
connect(m_table, SIGNAL(cellSelected(int, int)),
91
this, SLOT(slotCellSelected(int, int)));
92
connect(m_table->data(), SIGNAL(rowInserted(KexiDB::RecordData*, bool)),
93
this, SLOT(slotRowInserted(KexiDB::RecordData*, bool)));
95
//// Setup the icon toolbar /////////////////
96
QVBoxLayout *vlayout = new QVBoxLayout(layout);
97
m_addButton = new KPushButton(KIcon("document-new"), i18n("&New Connection"), frame);
98
vlayout->addWidget(m_addButton);
99
connect(m_addButton, SIGNAL(clicked()), this, SLOT(newItem()));
101
m_removeButton = new KPushButton(KIcon("edit-delete"), i18n("&Remove Connection"), frame);
102
vlayout->addWidget(m_removeButton);
103
connect(m_removeButton, SIGNAL(clicked()), this, SLOT(removeItem()));
105
vlayout->addStretch();
107
setInitialSize(QSize(600, 300));
108
//setWFlags(WDestructiveClose);
113
ConnectionDialog::~ConnectionDialog()
118
ConnectionDialog::initTable()
120
KexiTableViewColumn *col0 = new KexiTableViewColumn(i18n("OK?"), KexiDB::Field::Text);
121
col0->field()->setSubType("KIcon");
122
col0->setReadOnly(true);
123
col0->field()->setDescription(i18n("Connection correctness"));
124
m_data->addColumn(col0);
126
KexiTableViewColumn *col1 = new KexiTableViewColumn(i18n("Sender"), KexiDB::Field::Enum);
127
m_widgetsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text);
128
col1->setRelatedData(m_widgetsColumnData);
129
m_data->addColumn(col1);
131
KexiTableViewColumn *col2 = new KexiTableViewColumn(i18n("Signal"), KexiDB::Field::Enum);
132
m_signalsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text);
133
col2->setRelatedData(m_signalsColumnData);
134
m_data->addColumn(col2);
136
KexiTableViewColumn *col3 = new KexiTableViewColumn(i18n("Receiver"), KexiDB::Field::Enum);
137
col3->setRelatedData(m_widgetsColumnData);
138
m_data->addColumn(col3);
140
KexiTableViewColumn *col4 = new KexiTableViewColumn(i18n("Slot"), KexiDB::Field::Enum);
141
m_slotsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text);
142
col4->setRelatedData(m_slotsColumnData);
143
m_data->addColumn(col4);
147
m_table->maximizeColumnsWidth(c);
148
m_table->setColumnStretchEnabled(true, 4);
150
connect(m_data, SIGNAL(aboutToChangeCell(KexiDB::RecordData*, int, QVariant&, KexiDB::ResultInfo*)),
151
this, SLOT(slotCellChanged(KexiDB::RecordData*, int, QVariant, KexiDB::ResultInfo*)));
152
connect(m_data, SIGNAL(rowUpdated(KexiDB::RecordData*)), this, SLOT(checkConnection(KexiDB::RecordData*)));
153
connect(m_table, SIGNAL(itemSelected(KexiDB::RecordData*)), this, SLOT(checkConnection(KexiDB::RecordData*)));
156
void ConnectionDialog::exec()
162
void ConnectionDialog::slotCellSelected(int col, int row)
164
m_removeButton->setEnabled(row < m_table->rows());
165
KexiDB::RecordData *record = m_table->itemAt(row);
168
if (col == 2) // signal col
169
updateSignalList(record);
170
else if (col == 4) // slot col
171
updateSlotList(record);
174
void ConnectionDialog::slotRowInserted(KexiDB::RecordData* item, bool)
176
m_buffer->append(new Connection());
177
checkConnection(item);
181
ConnectionDialog::slotOk()
183
// First we update our buffer contents
184
for (int i = 0; i < m_table->rows(); i++) {
185
KexiDB::RecordData *record = m_table->itemAt(i);
186
Connection *c = m_buffer->at(i);
188
c->setSender((*record)[1].toString());
189
c->setSignal((*record)[2].toString());
190
c->setReceiver((*record)[3].toString());
191
c->setSlot((*record)[4].toString());
194
// then me make it replace form's current one
195
m_form->setConnectionBuffer(m_buffer);
201
ConnectionDialog::updateTableData()
203
// First we update the columns data
204
foreach (ObjectTreeItem *item, *m_form->objectTree()->hash()) {
205
KexiDB::RecordData *record = m_widgetsColumnData->createItem();
206
(*record)[0] = item->name();
207
(*record)[1] = (*record)[0];
208
m_widgetsColumnData->append(record);
211
// Then we fill the columns with the form connections
212
foreach (Connection *c, *m_form->connectionBuffer()) {
213
KexiDB::RecordData *record = m_table->data()->createItem();
214
(*record)[1] = c->sender();
215
(*record)[2] = c->signal();
216
(*record)[3] = c->receiver();
217
(*record)[4] = c->slot();
218
m_table->insertItem(record, m_table->rows());
221
m_buffer = new ConnectionBuffer(*(m_form->connectionBuffer()));
225
ConnectionDialog::setStatusOk(KexiDB::RecordData *record)
227
m_pixmapLabel->setPixmap(DesktopIcon("dialog-ok"));
228
m_textLabel->setText(i18n("<qt><h2>The connection is OK.</h2></qt>"));
231
record = m_table->selectedItem();
232
if (m_table->currentRow() >= m_table->rows())
236
(*record)[0] = "dialog-ok";
238
m_pixmapLabel->setPixmap(QPixmap());
239
m_textLabel->setText(QString());
244
ConnectionDialog::setStatusError(const QString &msg, KexiDB::RecordData *record)
246
m_pixmapLabel->setPixmap(DesktopIcon("dialog-cancel"));
247
m_textLabel->setText(i18n("<qt><h2>The connection is invalid.</h2></qt>") + msg);
250
record = m_table->selectedItem();
251
if (m_table->currentRow() >= m_table->rows())
255
(*record)[0] = "dialog-cancel";
257
m_pixmapLabel->setPixmap(QPixmap());
258
m_textLabel->setText(QString());
263
ConnectionDialog::slotCellChanged(KexiDB::RecordData *record, int col, QVariant&, KexiDB::ResultInfo*)
266
// sender changed, we clear siganl and slot
268
(*record)[2] = QString("");
269
// signal or receiver changed, we clear the slot cell
272
(*record)[4] = QString("");
281
ConnectionDialog::updateSlotList(KexiDB::RecordData *record)
283
m_slotsColumnData->deleteAllRows();
284
QString widget = (*record)[1].toString();
285
QString signal = (*record)[2].toString();
287
if ((widget.isEmpty()) || signal.isEmpty())
289
ObjectTreeItem *tree = m_form->objectTree()->lookup(widget);
290
if (!tree || !tree->widget())
293
QString signalArg(signal);
294
signalArg = signalArg.remove(QRegExp(".*[(]|[)]"));
296
const QList<QMetaMethod> list(
297
KexiUtils::methodsForMetaObjectWithParents(tree->widget()->metaObject(),
298
QMetaMethod::Slot, QMetaMethod::Public));
299
foreach(QMetaMethod method, list) {
300
// we add the slot only if it is compatible with the signal
301
QString slotArg(method.signature());
302
slotArg = slotArg.remove(QRegExp(".*[(]|[)]"));
303
if (!signalArg.startsWith(slotArg, Qt::CaseSensitive) && (!signal.isEmpty())) // args not compatible
306
KexiDB::RecordData *record = m_slotsColumnData->createItem();
307
(*record)[0] = QString::fromLatin1(method.signature());
308
(*record)[1] = (*record)[0];
309
m_slotsColumnData->append(record);
314
ConnectionDialog::updateSignalList(KexiDB::RecordData *record)
316
ObjectTreeItem *tree = m_form->objectTree()->lookup((*record)[1].toString());
317
if (!tree || !tree->widget())
320
m_signalsColumnData->deleteAllRows();
321
const QList<QMetaMethod> list(
322
KexiUtils::methodsForMetaObjectWithParents(tree->widget()->metaObject(),
323
QMetaMethod::Signal, QMetaMethod::Public));
324
foreach(QMetaMethod method, list) {
325
KexiDB::RecordData *record = m_signalsColumnData->createItem();
326
(*record)[0] = QString::fromLatin1(method.signature());
327
(*record)[1] = (*record)[0];
328
m_signalsColumnData->append(record);
333
ConnectionDialog::checkConnection(KexiDB::RecordData *record)
335
// First we check if one column is empty
336
for (int i = 1; i < 5; i++) {
337
if (!record || (*record)[i].toString().isEmpty()) {
338
setStatusError(i18n("<qt>You have not selected item: <b>%1</b>.</qt>",
339
m_data->column(i)->captionAliasOrName()), record);
344
// Then we check if signal/slot args are compatible
345
QString signal = (*record)[2].toString();
346
signal = signal.remove(QRegExp(".*[(]|[)]")); // just keep the args list
347
QString slot = (*record)[4].toString();
348
slot = slot.remove(QRegExp(".*[(]|[)]"));
350
if (!signal.startsWith(slot, Qt::CaseSensitive)) {
351
setStatusError(i18n("The signal/slot arguments are not compatible."), record);
359
ConnectionDialog::newItem()
361
m_table->acceptRowEdit();
362
m_table->setCursorPosition(m_table->rows(), 1);
366
ConnectionDialog::newItemByDragnDrop()
368
m_form->enterConnectingState();
369
connect(m_form, SIGNAL(connectionAborted(KFormDesigner::Form*)),
370
this, SLOT(slotConnectionAborted(KFormDesigner::Form*)));
371
connect(m_form, SIGNAL(connectionCreated(KFormDesigner::Form*, Connection&)),
372
this, SLOT(slotConnectionCreated(KFormDesigner::Form*, Connection&)));
378
ConnectionDialog::slotConnectionCreated(KFormDesigner::Form *form, Connection &connection)
384
Connection *c = new Connection(connection);
385
KexiDB::RecordData *record = m_table->data()->createItem();
386
(*record)[1] = c->sender();
387
(*record)[2] = c->signal();
388
(*record)[3] = c->receiver();
389
(*record)[4] = c->slot();
390
m_table->insertItem(record, m_table->rows());
395
ConnectionDialog::slotConnectionAborted(KFormDesigner::Form *form)
405
ConnectionDialog::removeItem()
407
if (m_table->currentRow() == -1 || m_table->currentRow() >= m_table->rows())
411
= KMessageBox::warningYesNo(parentWidget(),
412
i18n("Do you want to delete this connection?"),
414
KGuiItem(i18n("&Delete Connection")),
415
KStandardGuiItem::no(),
416
"dontAskBeforeDeleteConnection"/*config entry*/);
417
if (confirm != KMessageBox::Yes)
420
m_buffer->removeAt(m_table->currentRow());
421
m_table->deleteItem(m_table->selectedItem());
424
#include "connectiondialog.moc"