~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to kexi/formeditor/connectiondialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>
 
4
 
 
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.
 
9
 
 
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.
 
14
 
 
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.
 
19
*/
 
20
 
 
21
#include "connectiondialog.h"
 
22
 
 
23
#include <qlayout.h>
 
24
#include <qlabel.h>
 
25
#include <qregexp.h>
 
26
#include <qmetaobject.h>
 
27
 
 
28
#include <kpushbutton.h>
 
29
#include <kiconloader.h>
 
30
#include <kmessagebox.h>
 
31
#include <kdebug.h>
 
32
#include <klocale.h>
 
33
 
 
34
#include "kexitableview.h"
 
35
#include "kexitableviewdata.h"
 
36
 
 
37
#include "events.h"
 
38
#include "form.h"
 
39
//#include "formmanager.h"
 
40
#include "objecttree.h"
 
41
 
 
42
 
 
43
using namespace KFormDesigner;
 
44
 
 
45
/////////////////////////////////////////////////////////////////////////////////
 
46
///////////// The dialog to edit or add/remove connections //////////////////////
 
47
/////////////////////////////////////////////////////////////////////////////////
 
48
ConnectionDialog::ConnectionDialog(Form *form, QWidget *parent)
 
49
        : KDialog(parent)
 
50
        , m_buffer(0)
 
51
        , m_form(form)
 
52
{
 
53
    setObjectName("connections_dialog");
 
54
    setModal(true);
 
55
    setWindowTitle(i18n("Edit Form Connections"));
 
56
    setButtons(KDialog::Ok | KDialog::Cancel | KDialog::Details);
 
57
    setDefaultButton(KDialog::Ok);
 
58
 
 
59
    QFrame *frame = new QFrame(this);
 
60
    setMainWidget(frame);
 
61
    QHBoxLayout *layout = new QHBoxLayout(frame);
 
62
 
 
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);
 
69
 
 
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);
 
74
 
 
75
    m_textLabel = new QLabel(details);
 
76
    detailsLyr->addWidget(m_textLabel);
 
77
    m_textLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
 
78
    //setStatusOk();
 
79
 
 
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);
 
85
    initTable();
 
86
    m_table->setData(m_data, false);
 
87
    m_table->adjustColumnWidthToContents(0);
 
88
    layout->addWidget(m_table);
 
89
 
 
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)));
 
94
 
 
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()));
 
100
 
 
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()));
 
104
 
 
105
    vlayout->addStretch();
 
106
 
 
107
    setInitialSize(QSize(600, 300));
 
108
    //setWFlags(WDestructiveClose);
 
109
 
 
110
    this->newItem();
 
111
}
 
112
 
 
113
ConnectionDialog::~ConnectionDialog()
 
114
{
 
115
}
 
116
 
 
117
void
 
118
ConnectionDialog::initTable()
 
119
{
 
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);
 
125
 
 
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);
 
130
 
 
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);
 
135
 
 
136
    KexiTableViewColumn *col3 = new KexiTableViewColumn(i18n("Receiver"), KexiDB::Field::Enum);
 
137
    col3->setRelatedData(m_widgetsColumnData);
 
138
    m_data->addColumn(col3);
 
139
 
 
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);
 
144
 
 
145
    QList<int> c;
 
146
    c << 2 << 4;
 
147
    m_table->maximizeColumnsWidth(c);
 
148
    m_table->setColumnStretchEnabled(true, 4);
 
149
 
 
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*)));
 
154
}
 
155
 
 
156
void ConnectionDialog::exec()
 
157
{
 
158
    updateTableData();
 
159
    KDialog::exec();
 
160
}
 
161
 
 
162
void ConnectionDialog::slotCellSelected(int col, int row)
 
163
{
 
164
    m_removeButton->setEnabled(row < m_table->rows());
 
165
    KexiDB::RecordData *record = m_table->itemAt(row);
 
166
    if (!record)
 
167
        return;
 
168
    if (col == 2) // signal col
 
169
        updateSignalList(record);
 
170
    else if (col == 4) // slot col
 
171
        updateSlotList(record);
 
172
}
 
173
 
 
174
void ConnectionDialog::slotRowInserted(KexiDB::RecordData* item, bool)
 
175
{
 
176
    m_buffer->append(new Connection());
 
177
    checkConnection(item);
 
178
}
 
179
 
 
180
void
 
181
ConnectionDialog::slotOk()
 
182
{
 
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);
 
187
 
 
188
        c->setSender((*record)[1].toString());
 
189
        c->setSignal((*record)[2].toString());
 
190
        c->setReceiver((*record)[3].toString());
 
191
        c->setSlot((*record)[4].toString());
 
192
    }
 
193
 
 
194
    // then me make it replace form's current one
 
195
    m_form->setConnectionBuffer(m_buffer);
 
196
 
 
197
    QDialog::accept();
 
198
}
 
199
 
 
200
void
 
201
ConnectionDialog::updateTableData()
 
202
{
 
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);
 
209
    }
 
210
 
 
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());
 
219
    }
 
220
 
 
221
    m_buffer = new ConnectionBuffer(*(m_form->connectionBuffer()));
 
222
}
 
223
 
 
224
void
 
225
ConnectionDialog::setStatusOk(KexiDB::RecordData *record)
 
226
{
 
227
    m_pixmapLabel->setPixmap(DesktopIcon("dialog-ok"));
 
228
    m_textLabel->setText(i18n("<qt><h2>The connection is OK.</h2></qt>"));
 
229
 
 
230
    if (!record)
 
231
        record = m_table->selectedItem();
 
232
    if (m_table->currentRow() >= m_table->rows())
 
233
        record = 0;
 
234
 
 
235
    if (record)
 
236
        (*record)[0] = "dialog-ok";
 
237
    else {
 
238
        m_pixmapLabel->setPixmap(QPixmap());
 
239
        m_textLabel->setText(QString());
 
240
    }
 
241
}
 
242
 
 
243
void
 
244
ConnectionDialog::setStatusError(const QString &msg, KexiDB::RecordData *record)
 
245
{
 
246
    m_pixmapLabel->setPixmap(DesktopIcon("dialog-cancel"));
 
247
    m_textLabel->setText(i18n("<qt><h2>The connection is invalid.</h2></qt>") + msg);
 
248
 
 
249
    if (!record)
 
250
        record = m_table->selectedItem();
 
251
    if (m_table->currentRow() >= m_table->rows())
 
252
        record = 0;
 
253
 
 
254
    if (record)
 
255
        (*record)[0] = "dialog-cancel";
 
256
    else {
 
257
        m_pixmapLabel->setPixmap(QPixmap());
 
258
        m_textLabel->setText(QString());
 
259
    }
 
260
}
 
261
 
 
262
void
 
263
ConnectionDialog::slotCellChanged(KexiDB::RecordData *record, int col, QVariant&, KexiDB::ResultInfo*)
 
264
{
 
265
    switch (col) {
 
266
        // sender changed, we clear siganl and slot
 
267
    case 1:
 
268
        (*record)[2] = QString("");
 
269
        // signal or receiver changed, we clear the slot cell
 
270
    case 2:
 
271
    case 3: {
 
272
        (*record)[4] = QString("");
 
273
        break;
 
274
    }
 
275
    default:
 
276
        break;
 
277
    }
 
278
}
 
279
 
 
280
void
 
281
ConnectionDialog::updateSlotList(KexiDB::RecordData *record)
 
282
{
 
283
    m_slotsColumnData->deleteAllRows();
 
284
    QString widget = (*record)[1].toString();
 
285
    QString signal = (*record)[2].toString();
 
286
 
 
287
    if ((widget.isEmpty()) || signal.isEmpty())
 
288
        return;
 
289
    ObjectTreeItem *tree = m_form->objectTree()->lookup(widget);
 
290
    if (!tree || !tree->widget())
 
291
        return;
 
292
 
 
293
    QString signalArg(signal);
 
294
    signalArg = signalArg.remove(QRegExp(".*[(]|[)]"));
 
295
 
 
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
 
304
            continue;
 
305
 
 
306
        KexiDB::RecordData *record = m_slotsColumnData->createItem();
 
307
        (*record)[0] = QString::fromLatin1(method.signature());
 
308
        (*record)[1] = (*record)[0];
 
309
        m_slotsColumnData->append(record);
 
310
    }
 
311
}
 
312
 
 
313
void
 
314
ConnectionDialog::updateSignalList(KexiDB::RecordData *record)
 
315
{
 
316
    ObjectTreeItem *tree = m_form->objectTree()->lookup((*record)[1].toString());
 
317
    if (!tree || !tree->widget())
 
318
        return;
 
319
 
 
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);
 
329
    }
 
330
}
 
331
 
 
332
void
 
333
ConnectionDialog::checkConnection(KexiDB::RecordData *record)
 
334
{
 
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);
 
340
            return;
 
341
        }
 
342
    }
 
343
 
 
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(".*[(]|[)]"));
 
349
 
 
350
    if (!signal.startsWith(slot, Qt::CaseSensitive)) {
 
351
        setStatusError(i18n("The signal/slot arguments are not compatible."), record);
 
352
        return;
 
353
    }
 
354
 
 
355
    setStatusOk(record);
 
356
}
 
357
 
 
358
void
 
359
ConnectionDialog::newItem()
 
360
{
 
361
    m_table->acceptRowEdit();
 
362
    m_table->setCursorPosition(m_table->rows(), 1);
 
363
}
 
364
 
 
365
void
 
366
ConnectionDialog::newItemByDragnDrop()
 
367
{
 
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&)));
 
373
 
 
374
    hide();
 
375
}
 
376
 
 
377
void
 
378
ConnectionDialog::slotConnectionCreated(KFormDesigner::Form *form, Connection &connection)
 
379
{
 
380
    show();
 
381
    if (form != m_form)
 
382
        return;
 
383
 
 
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());
 
391
    m_buffer->append(c);
 
392
}
 
393
 
 
394
void
 
395
ConnectionDialog::slotConnectionAborted(KFormDesigner::Form *form)
 
396
{
 
397
    show();
 
398
    if (form != m_form)
 
399
        return;
 
400
 
 
401
    newItem();
 
402
}
 
403
 
 
404
void
 
405
ConnectionDialog::removeItem()
 
406
{
 
407
    if (m_table->currentRow() == -1 || m_table->currentRow() >= m_table->rows())
 
408
        return;
 
409
 
 
410
    const int confirm
 
411
        = KMessageBox::warningYesNo(parentWidget(),
 
412
              i18n("Do you want to delete this connection?"),
 
413
              QString(),
 
414
              KGuiItem(i18n("&Delete Connection")),
 
415
              KStandardGuiItem::no(),
 
416
              "dontAskBeforeDeleteConnection"/*config entry*/);
 
417
    if (confirm != KMessageBox::Yes)
 
418
        return;
 
419
 
 
420
    m_buffer->removeAt(m_table->currentRow());
 
421
    m_table->deleteItem(m_table->selectedItem());
 
422
}
 
423
 
 
424
#include "connectiondialog.moc"