kexi

connectiondialog.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
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     // Setup the details widget /////////
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     //setStatusOk();
00068 
00069     // And the KexiTableView ////////
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     //setWFlags(WDestructiveClose);
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) // signal col
00156         updateSignalList(item);
00157     else if(col == 4) // slot col
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     // First we update our buffer contents
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     // then me make it replace form's current one
00183     delete m_form->connectionBuffer();
00184     m_form->setConnectionBuffer(m_buffer);
00185 
00186     QDialog::accept();
00187 }
00188 
00189 void
00190 ConnectionDialog::updateTableData()
00191 {
00192     // First we update the columns data
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(); //new KexiTableItem(2);
00198         (*item)[0] = it.current()->name();
00199         (*item)[1] = (*item)[0];
00200         m_widgetsColumnData->append(item);
00201     }
00202     delete dict;
00203 
00204     // Then we fill the columns with the form connections
00205     for(Connection *c = m_form->connectionBuffer()->first(); c ; c = m_form->connectionBuffer()->next())
00206     {
00207         KexiTableItem *item = m_table->data()->createItem(); //new KexiTableItem(5);
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         // sender changed, we clear siganl and slot
00262         case 1:
00263             (*item)[2] = QString("");
00264         // signal or receiver changed, we clear the slot cell
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         // we add the slot only if it is compatible with the signal
00297         QString slotArg(*it);
00298         slotArg = slotArg.remove( QRegExp(".*[(]|[)]") );
00299 
00300         if(!signalArg.startsWith(slotArg, true) && (!signal.isEmpty())) // args not compatible
00301             continue;
00302 
00303         KexiTableItem *item = m_slotsColumnData->createItem(); //new KexiTableItem(2);
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(); //new KexiTableItem(2);
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     // First we check if one column is empty
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     // Then we check if signal/slot args are compatible
00344     QString signal = (*item)[2].toString();
00345     signal = signal.remove( QRegExp(".*[(]|[)]") ); // just keep the args list
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(); //new KexiTableItem(5);
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"/*config entry*/);
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"
KDE Home | KDE Accessibility Home | Description of Access Keys