00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qlayout.h>
00022 #include <qhbox.h>
00023 #include <qlabel.h>
00024 #include <qregexp.h>
00025 #include <qmetaobject.h>
00026 #include <qstrlist.h>
00027
00028 #include <kpushbutton.h>
00029 #include <kiconloader.h>
00030 #include <kmessagebox.h>
00031 #include <kdebug.h>
00032 #include <klocale.h>
00033
00034 #include "kexitableview.h"
00035 #include "kexitableviewdata.h"
00036 #include "events.h"
00037 #include "form.h"
00038 #include "formmanager.h"
00039 #include "objecttree.h"
00040
00041 #include "connectiondialog.h"
00042
00043 namespace KFormDesigner {
00044
00048 ConnectionDialog::ConnectionDialog(QWidget *parent)
00049 : KDialogBase(parent, "connections_dialog", true, i18n("Edit Form Connections"),
00050 Ok|Cancel|Details, Ok, false)
00051 , m_buffer(0)
00052 {
00053 QFrame *frame = makeMainWidget();
00054 QHBoxLayout *layout = new QHBoxLayout(frame, 0, 6);
00055
00056
00057 QHBox *details = new QHBox(frame);
00058 setDetailsWidget(details);
00059 setDetails(true);
00060
00061 m_pixmapLabel = new QLabel(details);
00062 m_pixmapLabel->setFixedWidth( int(IconSize(KIcon::Desktop) * 1.5) );
00063 m_pixmapLabel->setAlignment(AlignHCenter | AlignTop);
00064
00065 m_textLabel = new QLabel(details);
00066 m_textLabel->setAlignment(AlignLeft | AlignTop);
00067
00068
00069
00070 m_data = new KexiTableViewData();
00071 m_table = new KexiTableView(0, frame, "connections_tableview");
00072 m_table->setSpreadSheetMode();
00073 m_table->setInsertingEnabled(true);
00074 initTable();
00075 m_table->setData(m_data, false);
00076 m_table->adjustColumnWidthToContents(0);
00077 layout->addWidget(m_table);
00078
00080 QVBoxLayout *vlayout = new QVBoxLayout(layout, 3);
00081 KPushButton *newItem = new KPushButton(SmallIconSet("filenew"), i18n("&New Connection"), frame);
00082 vlayout->addWidget(newItem);
00083 m_buttons.insert(BAdd, newItem);
00084 connect(newItem, SIGNAL(clicked()), this, SLOT(newItem()));
00085
00086 KPushButton *delItem = new KPushButton(SmallIconSet("editdelete"), i18n("&Remove Connection"), frame);
00087 vlayout->addWidget(delItem);
00088 m_buttons.insert(BRemove, delItem);
00089 connect(delItem, SIGNAL(clicked()), this, SLOT(removeItem()));
00090
00091 vlayout->addStretch();
00092
00093 setInitialSize(QSize(600, 300));
00094
00095
00096 connect(m_table,SIGNAL(cellSelected(int, int)), this, SLOT(slotCellSelected(int, int)));
00097 connect(m_table->data(), SIGNAL(rowInserted(KexiTableItem*,bool)), this, SLOT(slotRowInserted(KexiTableItem*,bool)));
00098 this->newItem();
00099 }
00100
00101 void
00102 ConnectionDialog::initTable()
00103 {
00104 KexiTableViewColumn *col0 = new KexiTableViewColumn(i18n("OK?"), KexiDB::Field::Text);
00105 col0->field()->setSubType("KIcon");
00106 col0->setReadOnly(true);
00107 col0->field()->setDescription(i18n("Connection correctness"));
00108 m_data->addColumn(col0);
00109
00110 KexiTableViewColumn *col1 = new KexiTableViewColumn(i18n("Sender"), KexiDB::Field::Enum);
00111 m_widgetsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text);
00112 col1->setRelatedData( m_widgetsColumnData );
00113 m_data->addColumn(col1);
00114
00115 KexiTableViewColumn *col2 = new KexiTableViewColumn(i18n("Signal"), KexiDB::Field::Enum);
00116 m_signalsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text);
00117 col2->setRelatedData( m_signalsColumnData );
00118 m_data->addColumn(col2);
00119
00120 KexiTableViewColumn *col3 = new KexiTableViewColumn(i18n("Receiver"), KexiDB::Field::Enum);
00121 col3->setRelatedData( m_widgetsColumnData );
00122 m_data->addColumn(col3);
00123
00124 KexiTableViewColumn *col4 = new KexiTableViewColumn(i18n("Slot"), KexiDB::Field::Enum);
00125 m_slotsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text);
00126 col4->setRelatedData( m_slotsColumnData );
00127 m_data->addColumn(col4);
00128
00129 QValueList<int> c;
00130 c << 2 << 4;
00131 m_table->maximizeColumnsWidth(c);
00132 m_table->setColumnStretchEnabled( true, 4 );
00133
00134 connect(m_data, SIGNAL(aboutToChangeCell(KexiTableItem*, int, QVariant&, KexiDB::ResultInfo*)),
00135 this,SLOT(slotCellChanged(KexiTableItem*, int, QVariant, KexiDB::ResultInfo*)));
00136 connect(m_data, SIGNAL(rowUpdated(KexiTableItem*)), this, SLOT(checkConnection(KexiTableItem *)));
00137 connect(m_table, SIGNAL(itemSelected(KexiTableItem *)), this, SLOT(checkConnection(KexiTableItem *)));
00138 }
00139
00140 void
00141 ConnectionDialog::exec(Form *form)
00142 {
00143 m_form = form;
00144 updateTableData();
00145
00146 KDialogBase::exec();
00147 }
00148
00149 void ConnectionDialog::slotCellSelected(int col, int row)
00150 {
00151 m_buttons[BRemove]->setEnabled( row < m_table->rows() );
00152 KexiTableItem *item = m_table->itemAt(row);
00153 if (!item)
00154 return;
00155 if(col == 2)
00156 updateSignalList(item);
00157 else if(col == 4)
00158 updateSlotList(item);
00159 }
00160
00161 void ConnectionDialog::slotRowInserted(KexiTableItem* item,bool)
00162 {
00163 m_buffer->append(new Connection());
00164 checkConnection( item );
00165 }
00166
00167 void
00168 ConnectionDialog::slotOk()
00169 {
00170
00171 for(int i=0; i < m_table->rows(); i++)
00172 {
00173 KexiTableItem *item = m_table->itemAt(i);
00174 Connection *c = m_buffer->at(i);
00175
00176 c->setSender( (*item)[1].toString() );
00177 c->setSignal( (*item)[2].toString() );
00178 c->setReceiver( (*item)[3].toString() );
00179 c->setSlot( (*item)[4].toString() );
00180 }
00181
00182
00183 delete m_form->connectionBuffer();
00184 m_form->setConnectionBuffer(m_buffer);
00185
00186 QDialog::accept();
00187 }
00188
00189 void
00190 ConnectionDialog::updateTableData()
00191 {
00192
00193 ObjectTreeDict *dict = new ObjectTreeDict( *(m_form->objectTree()->dict()) );
00194 ObjectTreeDictIterator it(*dict);
00195 for(; it.current(); ++it)
00196 {
00197 KexiTableItem *item = m_widgetsColumnData->createItem();
00198 (*item)[0] = it.current()->name();
00199 (*item)[1] = (*item)[0];
00200 m_widgetsColumnData->append(item);
00201 }
00202 delete dict;
00203
00204
00205 for(Connection *c = m_form->connectionBuffer()->first(); c ; c = m_form->connectionBuffer()->next())
00206 {
00207 KexiTableItem *item = m_table->data()->createItem();
00208 (*item)[1] = c->sender();
00209 (*item)[2] = c->signal();
00210 (*item)[3] = c->receiver();
00211 (*item)[4] = c->slot();
00212 m_table->insertItem(item, m_table->rows());
00213 }
00214
00215 m_buffer = new ConnectionBuffer(*(m_form->connectionBuffer()));
00216 }
00217
00218 void
00219 ConnectionDialog::setStatusOk(KexiTableItem *item)
00220 {
00221 m_pixmapLabel->setPixmap( DesktopIcon("button_ok") );
00222 m_textLabel->setText("<qt><h2>The connection is OK.</h2></qt>");
00223
00224 if (!item)
00225 item = m_table->selectedItem();
00226 if (m_table->currentRow() >= m_table->rows())
00227 item = 0;
00228
00229 if (item)
00230 (*item)[0] = "button_ok";
00231 else {
00232 m_pixmapLabel->setPixmap( QPixmap() );
00233 m_textLabel->setText(QString::null);
00234 }
00235 }
00236
00237 void
00238 ConnectionDialog::setStatusError(const QString &msg, KexiTableItem *item)
00239 {
00240 m_pixmapLabel->setPixmap( DesktopIcon("button_cancel") );
00241 m_textLabel->setText("<qt><h2>The connection is invalid.</h2></qt>" + msg);
00242
00243 if (!item)
00244 item = m_table->selectedItem();
00245 if (m_table->currentRow() >= m_table->rows())
00246 item = 0;
00247
00248 if (item)
00249 (*item)[0] = "button_cancel";
00250 else {
00251 m_pixmapLabel->setPixmap( QPixmap() );
00252 m_textLabel->setText(QString::null);
00253 }
00254 }
00255
00256 void
00257 ConnectionDialog::slotCellChanged(KexiTableItem *item, int col, QVariant&, KexiDB::ResultInfo*)
00258 {
00259 switch(col)
00260 {
00261
00262 case 1:
00263 (*item)[2] = QString("");
00264
00265 case 2:
00266 case 3:
00267 {
00268 (*item)[4] = QString("");
00269 break;
00270 }
00271 default:
00272 break;
00273 }
00274 }
00275
00276 void
00277 ConnectionDialog::updateSlotList(KexiTableItem *item)
00278 {
00279 m_slotsColumnData->deleteAllRows();
00280 QString widget = (*item)[1].toString();
00281 QString signal = (*item)[2].toString();
00282
00283 if((widget.isEmpty()) || signal.isEmpty())
00284 return;
00285 ObjectTreeItem *tree = m_form->objectTree()->lookup(widget);
00286 if(!tree || !tree->widget())
00287 return;
00288
00289 QString signalArg(signal);
00290 signalArg = signalArg.remove( QRegExp(".*[(]|[)]") );
00291
00292 QStrList slotList = tree->widget()->metaObject()->slotNames(true);
00293 QStrListIterator it(slotList);
00294 for(; it.current() != 0; ++it)
00295 {
00296
00297 QString slotArg(*it);
00298 slotArg = slotArg.remove( QRegExp(".*[(]|[)]") );
00299
00300 if(!signalArg.startsWith(slotArg, true) && (!signal.isEmpty()))
00301 continue;
00302
00303 KexiTableItem *item = m_slotsColumnData->createItem();
00304 (*item)[0] = QString(*it);
00305 (*item)[1] = (*item)[0];
00306 m_slotsColumnData->append(item);
00307 }
00308 }
00309
00310 void
00311 ConnectionDialog::updateSignalList(KexiTableItem *item)
00312 {
00313 ObjectTreeItem *tree = m_form->objectTree()->lookup((*item)[1].toString());
00314 if(!tree || !tree->widget())
00315 return;
00316
00317 m_signalsColumnData->deleteAllRows();
00318 QStrList signalList = tree->widget()->metaObject()->signalNames(true);
00319 QStrListIterator it(signalList);
00320 for(; it.current() != 0; ++it)
00321 {
00322 KexiTableItem *item = m_signalsColumnData->createItem();
00323 (*item)[0] = QString(*it);
00324 (*item)[1] = (*item)[0];
00325 m_signalsColumnData->append(item);
00326 }
00327 }
00328
00329 void
00330 ConnectionDialog::checkConnection(KexiTableItem *item)
00331 {
00332
00333 for(int i = 1; i < 5; i++)
00334 {
00335 if( !item || (*item)[i].toString().isEmpty())
00336 {
00337 setStatusError( i18n("<qt>You have not selected item: <b>%1</b>.</qt>").arg(m_data->column(i)->captionAliasOrName()),
00338 item);
00339 return;
00340 }
00341 }
00342
00343
00344 QString signal = (*item)[2].toString();
00345 signal = signal.remove( QRegExp(".*[(]|[)]") );
00346 QString slot = (*item)[4].toString();
00347 slot = slot.remove( QRegExp(".*[(]|[)]") );
00348
00349 if(!signal.startsWith(slot, true))
00350 {
00351 setStatusError( i18n("The signal/slot arguments are not compatible."), item);
00352 return;
00353 }
00354
00355 setStatusOk(item);
00356 }
00357
00358 void
00359 ConnectionDialog::newItem()
00360 {
00361 m_table->acceptRowEdit();
00362 m_table->setCursorPosition(m_table->rows(), 1);
00363 }
00364
00365 void
00366 ConnectionDialog::newItemByDragnDrop()
00367 {
00368 KFormDesigner::FormManager::self()->startCreatingConnection();
00369 connect(KFormDesigner::FormManager::self(), SIGNAL(connectionAborted(KFormDesigner::Form*)), this, SLOT(slotConnectionAborted(KFormDesigner::Form*)));
00370 connect(KFormDesigner::FormManager::self(), SIGNAL(connectionCreated(KFormDesigner::Form*, Connection&)), this, SLOT(slotConnectionCreated(KFormDesigner::Form*, Connection&)) );
00371
00372 hide();
00373 }
00374
00375 void
00376 ConnectionDialog::slotConnectionCreated(KFormDesigner::Form *form, Connection &connection)
00377 {
00378 show();
00379 if(form != m_form)
00380 return;
00381
00382 Connection *c = new Connection(connection);
00383 KexiTableItem *item = m_table->data()->createItem();
00384 (*item)[1] = c->sender();
00385 (*item)[2] = c->signal();
00386 (*item)[3] = c->receiver();
00387 (*item)[4] = c->slot();
00388 m_table->insertItem(item, m_table->rows());
00389 m_buffer->append(c);
00390 }
00391
00392 void
00393 ConnectionDialog::slotConnectionAborted(KFormDesigner::Form *form)
00394 {
00395 show();
00396 if(form != m_form)
00397 return;
00398
00399 newItem();
00400 }
00401
00402 void
00403 ConnectionDialog::removeItem()
00404 {
00405 if(m_table->currentRow() == -1 || m_table->currentRow()>=m_table->rows())
00406 return;
00407
00408 int confirm = KMessageBox::warningContinueCancel(parentWidget(),
00409 QString("<qt>")+i18n("Do you want to delete this connection ?")+"</qt>", QString::null, KGuiItem(i18n("&Delete Connection")),
00410 "dontAskBeforeDeleteConnection");
00411 if(confirm == KMessageBox::Cancel)
00412 return;
00413
00414 m_buffer->remove(m_table->currentRow());
00415 m_table->deleteItem(m_table->selectedItem());
00416 }
00417
00418 }
00419
00420 #include "connectiondialog.moc"