/* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004 Jaroslaw Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include "kexitableview.h" #include "kexitableviewdata.h" #include "events.h" #include "form.h" #include "formmanager.h" #include "objecttree.h" #include "connectiondialog.h" namespace KFormDesigner { ///////////////////////////////////////////////////////////////////////////////// ///////////// The dialog to edit or add/remove connections ////////////////////// ///////////////////////////////////////////////////////////////////////////////// ConnectionDialog::ConnectionDialog(TQWidget *parent) : KDialogBase(parent, "connections_dialog", true, i18n("Edit Form Connections"), Ok|Cancel|Details, Ok, false) , m_buffer(0) { TQFrame *frame = makeMainWidget(); TQHBoxLayout *layout = new TQHBoxLayout(frame, 0, 6); // Setup the details widget ///////// TQHBox *details = new TQHBox(frame); setDetailsWidget(details); setDetails(true); m_pixmapLabel = new TQLabel(details); m_pixmapLabel->setFixedWidth( int(IconSize(TDEIcon::Desktop) * 1.5) ); m_pixmapLabel->setAlignment(AlignHCenter | AlignTop); m_textLabel = new TQLabel(details); m_textLabel->setAlignment(AlignLeft | AlignTop); //setStatusOk(); // And the KexiTableView //////// m_data = new KexiTableViewData(); m_table = new KexiTableView(0, frame, "connections_tableview"); m_table->setSpreadSheetMode(); m_table->setInsertingEnabled(true); initTable(); m_table->setData(m_data, false); m_table->adjustColumnWidthToContents(0); layout->addWidget(m_table); //// Setup the icon toolbar ///////////////// TQVBoxLayout *vlayout = new TQVBoxLayout(layout, 3); KPushButton *newItem = new KPushButton(SmallIconSet("filenew"), i18n("&New Connection"), frame); vlayout->addWidget(newItem); m_buttons.insert(BAdd, newItem); connect(newItem, TQT_SIGNAL(clicked()), this, TQT_SLOT(newItem())); KPushButton *delItem = new KPushButton(SmallIconSet("editdelete"), i18n("&Remove Connection"), frame); vlayout->addWidget(delItem); m_buttons.insert(BRemove, delItem); connect(delItem, TQT_SIGNAL(clicked()), this, TQT_SLOT(removeItem())); vlayout->addStretch(); setInitialSize(TQSize(600, 300)); //setWFlags(WDestructiveClose); connect(m_table,TQT_SIGNAL(cellSelected(int, int)), this, TQT_SLOT(slotCellSelected(int, int))); connect(m_table->KexiDataAwareObjectInterface::data(), TQT_SIGNAL(rowInserted(KexiTableItem*,bool)), this, TQT_SLOT(slotRowInserted(KexiTableItem*,bool))); this->newItem(); } void ConnectionDialog::initTable() { KexiTableViewColumn *col0 = new KexiTableViewColumn(i18n("OK?"), KexiDB::Field::Text); col0->field()->setSubType("TDEIcon"); col0->setReadOnly(true); col0->field()->setDescription(i18n("Connection correctness")); m_data->addColumn(col0); KexiTableViewColumn *col1 = new KexiTableViewColumn(i18n("Sender"), KexiDB::Field::Enum); m_widgetsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text); col1->setRelatedData( m_widgetsColumnData ); m_data->addColumn(col1); KexiTableViewColumn *col2 = new KexiTableViewColumn(i18n("Signal"), KexiDB::Field::Enum); m_signalsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text); col2->setRelatedData( m_signalsColumnData ); m_data->addColumn(col2); KexiTableViewColumn *col3 = new KexiTableViewColumn(i18n("Receiver"), KexiDB::Field::Enum); col3->setRelatedData( m_widgetsColumnData ); m_data->addColumn(col3); KexiTableViewColumn *col4 = new KexiTableViewColumn(i18n("Slot"), KexiDB::Field::Enum); m_slotsColumnData = new KexiTableViewData(KexiDB::Field::Text, KexiDB::Field::Text); col4->setRelatedData( m_slotsColumnData ); m_data->addColumn(col4); TQValueList c; c << 2 << 4; m_table->maximizeColumnsWidth(c); m_table->setColumnStretchEnabled( true, 4 ); connect(m_data, TQT_SIGNAL(aboutToChangeCell(KexiTableItem*, int, TQVariant&, KexiDB::ResultInfo*)), this,TQT_SLOT(slotCellChanged(KexiTableItem*, int, TQVariant, KexiDB::ResultInfo*))); connect(m_data, TQT_SIGNAL(rowUpdated(KexiTableItem*)), this, TQT_SLOT(checkConnection(KexiTableItem *))); connect(m_table, TQT_SIGNAL(itemSelected(KexiTableItem *)), this, TQT_SLOT(checkConnection(KexiTableItem *))); } void ConnectionDialog::exec(Form *form) { m_form = form; updateTableData(); KDialogBase::exec(); } void ConnectionDialog::slotCellSelected(int col, int row) { m_buttons[BRemove]->setEnabled( row < m_table->rows() ); KexiTableItem *item = m_table->itemAt(row); if (!item) return; if(col == 2) // signal col updateSignalList(item); else if(col == 4) // slot col updateSlotList(item); } void ConnectionDialog::slotRowInserted(KexiTableItem* item,bool) { m_buffer->append(new Connection()); checkConnection( item ); } void ConnectionDialog::slotOk() { // First we update our buffer contents for(int i=0; i < m_table->rows(); i++) { KexiTableItem *item = m_table->itemAt(i); Connection *c = m_buffer->at(i); c->setSender( (*item)[1].toString() ); c->setSignal( (*item)[2].toString() ); c->setReceiver( (*item)[3].toString() ); c->setSlot( (*item)[4].toString() ); } // then me make it replace form's current one delete m_form->connectionBuffer(); m_form->setConnectionBuffer(m_buffer); TQDialog::accept(); } void ConnectionDialog::updateTableData() { // First we update the columns data ObjectTreeDict *dict = new ObjectTreeDict( *(m_form->objectTree()->dict()) ); ObjectTreeDictIterator it(*dict); for(; it.current(); ++it) { KexiTableItem *item = m_widgetsColumnData->createItem(); //new KexiTableItem(2); (*item)[0] = it.current()->name(); (*item)[1] = (*item)[0]; m_widgetsColumnData->append(item); } delete dict; // Then we fill the columns with the form connections for(Connection *c = m_form->connectionBuffer()->first(); c ; c = m_form->connectionBuffer()->next()) { KexiTableItem *item = m_table->KexiDataAwareObjectInterface::data()->createItem(); //new KexiTableItem(5); (*item)[1] = c->sender(); (*item)[2] = c->signal(); (*item)[3] = c->receiver(); (*item)[4] = c->slot(); m_table->insertItem(item, m_table->rows()); } m_buffer = new ConnectionBuffer(*(m_form->connectionBuffer())); } void ConnectionDialog::setStatusOk(KexiTableItem *item) { m_pixmapLabel->setPixmap( DesktopIcon("button_ok") ); m_textLabel->setText("

The connection is OK.

"); if (!item) item = m_table->selectedItem(); if (m_table->currentRow() >= m_table->rows()) item = 0; if (item) (*item)[0] = "button_ok"; else { m_pixmapLabel->setPixmap( TQPixmap() ); m_textLabel->setText(TQString()); } } void ConnectionDialog::setStatusError(const TQString &msg, KexiTableItem *item) { m_pixmapLabel->setPixmap( DesktopIcon("button_cancel") ); m_textLabel->setText("

The connection is invalid.

" + msg); if (!item) item = m_table->selectedItem(); if (m_table->currentRow() >= m_table->rows()) item = 0; if (item) (*item)[0] = "button_cancel"; else { m_pixmapLabel->setPixmap( TQPixmap() ); m_textLabel->setText(TQString()); } } void ConnectionDialog::slotCellChanged(KexiTableItem *item, int col, TQVariant&, KexiDB::ResultInfo*) { switch(col) { // sender changed, we clear siganl and slot case 1: (*item)[2] = TQString(""); // signal or receiver changed, we clear the slot cell case 2: case 3: { (*item)[4] = TQString(""); break; } default: break; } } void ConnectionDialog::updateSlotList(KexiTableItem *item) { m_slotsColumnData->deleteAllRows(); TQString widget = (*item)[1].toString(); TQString signal = (*item)[2].toString(); if((widget.isEmpty()) || signal.isEmpty()) return; ObjectTreeItem *tree = m_form->objectTree()->lookup(widget); if(!tree || !tree->widget()) return; TQString signalArg(signal); signalArg = signalArg.remove( TQRegExp(".*[(]|[)]") ); TQStrList slotList = tree->widget()->metaObject()->slotNames(true); TQStrListIterator it(slotList); for(; it.current() != 0; ++it) { // we add the slot only if it is compatible with the signal TQString slotArg(*it); slotArg = slotArg.remove( TQRegExp(".*[(]|[)]") ); if(!signalArg.startsWith(slotArg, true) && (!signal.isEmpty())) // args not compatible continue; KexiTableItem *item = m_slotsColumnData->createItem(); //new KexiTableItem(2); (*item)[0] = TQString(*it); (*item)[1] = (*item)[0]; m_slotsColumnData->append(item); } } void ConnectionDialog::updateSignalList(KexiTableItem *item) { ObjectTreeItem *tree = m_form->objectTree()->lookup((*item)[1].toString()); if(!tree || !tree->widget()) return; m_signalsColumnData->deleteAllRows(); TQStrList signalList = tree->widget()->metaObject()->signalNames(true); TQStrListIterator it(signalList); for(; it.current() != 0; ++it) { KexiTableItem *item = m_signalsColumnData->createItem(); //new KexiTableItem(2); (*item)[0] = TQString(*it); (*item)[1] = (*item)[0]; m_signalsColumnData->append(item); } } void ConnectionDialog::checkConnection(KexiTableItem *item) { // First we check if one column is empty for(int i = 1; i < 5; i++) { if( !item || (*item)[i].toString().isEmpty()) { setStatusError( i18n("You have not selected item: %1.").arg(m_data->column(i)->captionAliasOrName()), item); return; } } // Then we check if signal/slot args are compatible TQString signal = (*item)[2].toString(); signal = signal.remove( TQRegExp(".*[(]|[)]") ); // just keep the args list TQString slot = (*item)[4].toString(); slot = slot.remove( TQRegExp(".*[(]|[)]") ); if(!signal.startsWith(slot, true)) { setStatusError( i18n("The signal/slot arguments are not compatible."), item); return; } setStatusOk(item); } void ConnectionDialog::newItem() { m_table->acceptRowEdit(); m_table->setCursorPosition(m_table->rows(), 1); } void ConnectionDialog::newItemByDragnDrop() { KFormDesigner::FormManager::self()->startCreatingConnection(); connect(KFormDesigner::FormManager::self(), TQT_SIGNAL(connectionAborted(KFormDesigner::Form*)), this, TQT_SLOT(slotConnectionAborted(KFormDesigner::Form*))); connect(KFormDesigner::FormManager::self(), TQT_SIGNAL(connectionCreated(KFormDesigner::Form*, Connection&)), this, TQT_SLOT(slotConnectionCreated(KFormDesigner::Form*, Connection&)) ); hide(); } void ConnectionDialog::slotConnectionCreated(KFormDesigner::Form *form, Connection &connection) { show(); if(form != m_form) return; Connection *c = new Connection(connection); KexiTableItem *item = m_table->KexiDataAwareObjectInterface::data()->createItem(); //new KexiTableItem(5); (*item)[1] = c->sender(); (*item)[2] = c->signal(); (*item)[3] = c->receiver(); (*item)[4] = c->slot(); m_table->insertItem(item, m_table->rows()); m_buffer->append(c); } void ConnectionDialog::slotConnectionAborted(KFormDesigner::Form *form) { show(); if(form != m_form) return; newItem(); } void ConnectionDialog::removeItem() { if(m_table->currentRow() == -1 || m_table->currentRow()>=m_table->rows()) return; int confirm = KMessageBox::warningContinueCancel(parentWidget(), TQString("")+i18n("Do you want to delete this connection ?")+"", TQString(), KGuiItem(i18n("&Delete Connection")), "dontAskBeforeDeleteConnection"/*config entry*/); if(confirm == KMessageBox::Cancel) return; m_buffer->remove(m_table->currentRow()); m_table->deleteItem(m_table->selectedItem()); } } #include "connectiondialog.moc"