kexi

kexialtertabledialog.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
00003 
00004    This program is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this program; see the file COPYING.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kexialtertabledialog.h"
00021 
00022 #include <qlayout.h>
00023 #include <qlabel.h>
00024 #include <qsplitter.h>
00025 
00026 #include <kiconloader.h>
00027 #include <kdebug.h>
00028 #include <klocale.h>
00029 #include <kaction.h>
00030 #include <kpopupmenu.h>
00031 #include <kmessagebox.h>
00032 
00033 #include <koproperty/set.h>
00034 #include <koproperty/property.h>
00035 
00036 #include <kexidb/cursor.h>
00037 #include <kexidb/tableschema.h>
00038 #include <kexidb/connection.h>
00039 #include <kexidb/utils.h>
00040 #include <kexidb/roweditbuffer.h>
00041 #include <kexidb/error.h>
00042 #include <kexiutils/identifier.h>
00043 #include <kexiproject.h>
00044 #include <keximainwindow.h>
00045 #include <widget/tableview/kexidataawarepropertyset.h>
00046 #include <widget/kexicustompropertyfactory.h>
00047 #include <kexidialogbase.h>
00048 #include <kexitableview.h>
00049 
00050 //#define MAX_FIELDS 101 //nice prime number
00051 
00053 #define COLUMN_ID_PK 0
00054 //#define COLUMN_ID_NAME 1
00055 #define COLUMN_ID_CAPTION 1
00056 #define COLUMN_ID_TYPE 2
00057 #define COLUMN_ID_DESC 3
00058 
00059 //#define KexiAlterTableDialog_DEBUG
00060 
00062 #define KEXI_NO_BLOB_FIELDS
00063 
00065 class KexiAlterTableDialogPrivate
00066 {
00067     public:
00068         KexiAlterTableDialogPrivate()
00069          : sets(0)
00070          , dontAskOnStoreData(false)
00071          , slotTogglePrimaryKeyCalled(false)
00072          , primaryKeyExists(false)
00073          , slotPropertyChanged_primaryKey_enabled(true)
00074          , slotPropertyChanged_subType_enabled(true)
00075         {
00076         }
00077 
00078         ~KexiAlterTableDialogPrivate() {
00079             delete sets;
00080         }
00081         
00082         KexiTableView *view; 
00083 
00084         KexiTableViewData *data;
00085 
00086         KexiDataAwarePropertySet *sets;
00087 
00088         int row; 
00089 
00090         KToggleAction *action_toggle_pkey;
00091 
00093         int maxTypeNameTextWidth;
00095         bool dontAskOnStoreData : 1;
00096 
00097         bool slotTogglePrimaryKeyCalled : 1;
00098 
00099         bool primaryKeyExists : 1;
00101         bool slotPropertyChanged_primaryKey_enabled : 1;
00103         bool slotPropertyChanged_subType_enabled : 1;
00104 };
00105 
00106 //----------------------------------------------
00107 
00108 KexiAlterTableDialog::KexiAlterTableDialog(KexiMainWindow *win, QWidget *parent,
00109     const char *name)
00110  : KexiDataTable(win, parent, name, false/*not db-aware*/)
00111  , d( new KexiAlterTableDialogPrivate() )
00112 {
00113     //needed for custom "identifier" property editor widget
00114     KexiCustomPropertyFactory::init();
00115 
00116     KexiDB::Connection *conn = mainWin()->project()->dbConnection();
00117 
00118     d->data = new KexiTableViewData();
00119     if (conn->isReadOnly())
00120         d->data->setReadOnly(true);
00121     d->data->setInsertingEnabled( false );
00122 
00123     KexiTableViewColumn *col = new KexiTableViewColumn("pk", KexiDB::Field::Text, i18n("Primary Key", "PK"),
00124         i18n("Describes primary key for the field."));
00125     col->field()->setSubType("KIcon");
00126     col->setReadOnly(true);
00127     d->data->addColumn( col );
00128 
00129 //  col = new KexiTableViewColumn("name", KexiDB::Field::Text, i18n("Field Name"),
00130     col = new KexiTableViewColumn("caption", KexiDB::Field::Text, i18n("Field Caption"),
00131         i18n("Describes name for the field."));
00132 //  KexiUtils::Validator *vd = new KexiUtils::IdentifierValidator();
00133 //  vd->setAcceptsEmptyValue(true);
00134 //  col->setValidator( vd );
00135     d->data->addColumn( col );
00136 
00137     col = new KexiTableViewColumn("type", KexiDB::Field::Enum, i18n("Data Type"),
00138         i18n("Describes data type for the field."));
00139     d->data->addColumn( col );
00140 
00141 #ifdef KEXI_NO_BLOB_FIELDS
00142 
00143     QValueVector<QString> types(KexiDB::Field::LastTypeGroup-1); //don't show last type (BLOB)
00144 #else
00145     QValueVector<QString> types(KexiDB::Field::LastTypeGroup);
00146 #endif
00147     d->maxTypeNameTextWidth = 0;
00148     QFontMetrics fm(font());
00149     for (uint i=1; i<=types.count(); i++) {
00150         types[i-1] = KexiDB::Field::typeGroupName(i);
00151         d->maxTypeNameTextWidth = QMAX(d->maxTypeNameTextWidth, fm.width(types[i-1]));
00152     }
00153     col->field()->setEnumHints(types);
00154 
00155     d->data->addColumn( col = new KexiTableViewColumn("comments", KexiDB::Field::Text, i18n("Comments"),
00156         i18n("Describes additional comments for the field.")) );
00157 
00158     d->view = dynamic_cast<KexiTableView*>(mainWidget());
00159 
00160     d->view->setSpreadSheetMode();
00161 //  setFocusProxy(d->view);
00162 
00163     connect(d->data, SIGNAL(aboutToChangeCell(KexiTableItem*,int,QVariant&,KexiDB::ResultInfo*)),
00164         this, SLOT(slotBeforeCellChanged(KexiTableItem*,int,QVariant&,KexiDB::ResultInfo*)));
00165     connect(d->data, SIGNAL(rowUpdated(KexiTableItem*)),
00166         this, SLOT(slotRowUpdated(KexiTableItem*)));
00167     connect(d->data, SIGNAL(aboutToInsertRow(KexiTableItem*,KexiDB::ResultInfo*,bool)),
00168         this, SLOT(slotAboutToInsertRow(KexiTableItem*,KexiDB::ResultInfo*,bool)));
00169     connect(d->data, SIGNAL(aboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)),
00170         this, SLOT(slotAboutToDeleteRow(KexiTableItem&,KexiDB::ResultInfo*,bool)));
00171 
00172     setMinimumSize(d->view->minimumSizeHint().width(), d->view->minimumSizeHint().height());
00173     d->view->setFocus();
00174 
00175     d->sets = new KexiDataAwarePropertySet( this, d->view );
00176     connect(d->sets, SIGNAL(rowDeleted()), this, SLOT(updateActions()));
00177     connect(d->sets, SIGNAL(rowInserted()), this, SLOT(updateActions()));
00178 
00179     plugSharedAction("tablepart_toggle_pkey", this, SLOT(slotTogglePrimaryKey()));
00180     d->action_toggle_pkey = static_cast<KToggleAction*>( sharedAction("tablepart_toggle_pkey") );
00181     d->action_toggle_pkey->plug(d->view->contextMenu(), 0); //add at the beg.
00182     setAvailable("tablepart_toggle_pkey", !conn->isReadOnly());
00183 }
00184 
00185 KexiAlterTableDialog::~KexiAlterTableDialog()
00186 {
00187 //  removeCurrentPropertySet();
00188     delete d;
00189 }
00190 
00191 void KexiAlterTableDialog::initData()
00192 {
00193     //add column data
00194 //  d->data->clear();
00195     d->data->deleteAllRows();
00196     int tableFieldCount = 0;
00197     d->primaryKeyExists = false;
00198 
00199     if (tempData()->table) {
00200         tableFieldCount = tempData()->table->fieldCount();
00201 //not needed        d->sets->clear(tableFieldCount);
00202 
00203         //recreate table data rows
00204         for(int i=0; i < tableFieldCount; i++) {
00205             KexiDB::Field *field = tempData()->table->field(i);
00206             KexiTableItem *item = d->data->createItem(); //new KexiTableItem(0);
00207             (*item)[0] = field->isPrimaryKey() ? "key" : "";
00208             if (field->isPrimaryKey())
00209                 d->primaryKeyExists = true;
00210             (*item)[1] = field->captionOrName();
00211             (*item)[2] = field->typeGroup()-1; //-1 because type groups are counted from 1
00212             (*item)[3] = field->description();
00213             d->data->append(item);
00214 
00215 //later!            createPropertySet( i, field );
00216         }
00217     }
00218 //  else {
00219 //      d->sets->clear();//default size
00220 //  }
00221 
00222     //add empty space
00223 //  const int columnsCount = d->data->columnsCount();
00224     for (int i=tableFieldCount; i<(int)d->sets->size(); i++) {
00225 //      KexiTableItem *item = new KexiTableItem(columnsCount);//3 empty fields
00226         d->data->append(d->data->createItem());
00227     }
00228 
00229     //set data for our spreadsheet: this will clear our sets
00230     d->view->setData(d->data);
00231 
00232     //now recreate property sets
00233     if (tempData()->table) {
00234         for(int i=0; i < tableFieldCount; i++) {
00235             KexiDB::Field *field = tempData()->table->field(i);
00236             createPropertySet( i, field );
00237         }
00238     }
00239 
00240     //column widths
00241     d->view->setColumnWidth(COLUMN_ID_PK, IconSize( KIcon::Small ) + 10);
00242     d->view->adjustColumnWidthToContents(COLUMN_ID_CAPTION); //adjust column width
00243     d->view->setColumnWidth(COLUMN_ID_TYPE, d->maxTypeNameTextWidth + 2 * d->view->rowHeight());
00244     d->view->setColumnStretchEnabled( true, COLUMN_ID_DESC ); //last column occupies the rest of the area
00245 
00246     setDirty(false);
00247     d->view->setCursorPosition(0, COLUMN_ID_CAPTION); //set @ name column
00248 }
00249 
00250 static bool updatePropertiesVisibility(KexiDB::Field::Type fieldType, KoProperty::Set &set)
00251 {
00252     bool changed = false;
00253     KoProperty::Property *prop;
00254     bool visible;
00255     
00256     prop = &set["subType"];
00257     const bool isObjectTypeGroup = set["type"].value().toInt() == (int)KexiDB::Field::BLOB;
00258     kdDebug() << prop->value().toInt() << set["type"].value().toInt()<< endl;
00259     
00260     //if there is no more than 1 subType name or it's a PK: hide the property
00261     visible = (prop->listData() && prop->listData()->keys.count() > 1 || isObjectTypeGroup)
00262         && set["primaryKey"].value().toBool()==false;
00263     if (prop->isVisible()!=visible) {
00264         prop->setVisible( visible );
00265         changed = true;
00266     }
00267     prop = &set["unsigned"];
00268     visible = KexiDB::Field::isNumericType(fieldType);
00269     if (prop->isVisible()!=visible) {
00270         prop->setVisible( visible );
00271         changed = true;
00272     }
00273     prop = &set["length"];
00274     visible = (fieldType == KexiDB::Field::Text);
00275     if (prop->isVisible()!=visible) {
00276         prop->setVisible( visible );
00277         prop->setValue( visible ? KexiDB::Field::defaultTextLength() : 0, false );
00278         changed = true;
00279     }
00280 #ifndef KEXI_NO_UNFINISHED
00281     prop = &set["precision"];
00282     visible = KexiDB::Field::isFPNumericType(fieldType);
00283     if (prop->isVisible()!=visible) {
00284         prop->setVisible( visible );
00285         changed = true;
00286     }
00287 #endif
00288     prop = &set["unique"];
00289     visible = fieldType != KexiDB::Field::BLOB;
00290     if (prop->isVisible()!=visible) {
00291         prop->setVisible( visible );
00292         changed = true;
00293     }
00294     prop = &set["indexed"];
00295     visible = fieldType != KexiDB::Field::BLOB;
00296     if (prop->isVisible()!=visible) {
00297         prop->setVisible( visible );
00298         changed = true;
00299     }
00300     prop = &set["allowEmpty"];
00301     visible = KexiDB::Field::hasEmptyProperty(fieldType);
00302     if (prop->isVisible()!=visible) {
00303         prop->setVisible( visible );
00304         changed = true;
00305     }
00306     prop = &set["autoIncrement"];
00307     visible = KexiDB::Field::isAutoIncrementAllowed(fieldType);
00308     if (prop->isVisible()!=visible) {
00309         prop->setVisible( visible );
00310         changed = true;
00311     }
00312     return changed;
00313 }
00314 
00316 void
00317 KexiAlterTableDialog::getSubTypeListData(KexiDB::Field::TypeGroup fieldTypeGroup, 
00318     QStringList& stringsList, QStringList& namesList)
00319 {
00320     if (fieldTypeGroup==KexiDB::Field::BLOBGroup) {
00321         // special case: BLOB type uses "mime-based" subtypes
00323         stringsList << "image";
00324         namesList << i18n("Image object type", "Image");
00325     }
00326     else {
00327         stringsList = KexiDB::typeStringsForGroup(fieldTypeGroup);
00328         namesList = KexiDB::typeNamesForGroup(fieldTypeGroup);
00329     }
00330     kdDebug() << "KexiAlterTableDialog::getSubTypeListData(): subType strings: " << 
00331         stringsList.join("|") << "\nnames: " << namesList.join("|") << endl;
00332 }
00333 
00334 KoProperty::Set *
00335 KexiAlterTableDialog::createPropertySet( int row, KexiDB::Field *field, bool newOne )
00336 {
00337     QString typeName = "KexiDB::Field::" + field->typeGroupString();
00338     KoProperty::Set *set = new KoProperty::Set(d->sets, typeName);
00339     if (mainWin()->project()->dbConnection()->isReadOnly())
00340         set->setReadOnly( true );
00341 //  connect(buff,SIGNAL(propertyChanged(KexiPropertyBuffer&,KexiProperty&)),
00342 //      this, SLOT(slotPropertyChanged(KexiPropertyBuffer&,KexiProperty&)));
00343 
00344     KoProperty::Property *prop;
00345 
00346     //meta-info for property editor
00347     set->addProperty(prop = new KoProperty::Property("this:classString", i18n("Table field")) );
00348     prop->setVisible(false);
00350 //  prop->setVisible(false);
00351 
00352     //name
00353     set->addProperty(prop 
00354         = new KoProperty::Property("name", QVariant(field->name()), i18n("Name"), 
00355         QString::null, KexiCustomPropertyFactory::Identifier) );
00356 
00357     //type
00358     set->addProperty( prop 
00359         = new KoProperty::Property("type", QVariant(field->type()), i18n("Type")) );
00360 #ifndef KexiAlterTableDialog_DEBUG
00361     prop->setVisible(false);//always hidden
00362 #endif
00363 
00364     //subtype
00365     QStringList slist, nlist;
00366     getSubTypeListData(field->typeGroup(), slist, nlist);
00367     QString subTypeValue;
00368     if (field->typeGroup()==KexiDB::Field::BLOBGroup) {
00369 // special case: BLOB type uses "mime-based" subtypes
00371         subTypeValue = slist.first();
00372     }
00373     else {
00374         subTypeValue = field->typeString();
00375     }
00376     set->addProperty(prop 
00377         = new KoProperty::Property("subType", slist, nlist, subTypeValue, i18n("Subtype")));
00378 
00379     set->addProperty( prop 
00380         = new KoProperty::Property("caption", QVariant(field->caption()), i18n("Caption") ) );
00381     prop->setVisible(false);//always hidden
00382 
00383     set->addProperty( prop 
00384         = new KoProperty::Property("description", QVariant(field->description())) );
00385     prop->setVisible(false);//always hidden
00386 
00387     set->addProperty(prop 
00388         = new KoProperty::Property("unsigned", QVariant(field->isUnsigned(), 4), i18n("Unsigned Number")));
00389 
00390     set->addProperty( prop 
00391         = new KoProperty::Property("length", (int)field->length()/*200?*/, i18n("Length")));
00392 
00393     set->addProperty( prop 
00394         = new KoProperty::Property("precision", (int)field->precision()/*200?*/, i18n("Precision")));
00395 #ifdef KEXI_NO_UNFINISHED
00396     prop->setVisible(false);
00397 #endif
00398 
00400     set->addProperty( prop 
00401         = new KoProperty::Property("width", (int)field->width()/*200?*/, i18n("Column Width")));
00402 #ifdef KEXI_NO_UNFINISHED
00403     prop->setVisible(false);
00404 #endif
00405 
00406     set->addProperty( prop 
00407         = new KoProperty::Property("defaultValue", field->defaultValue(), i18n("Default Value")));
00409     prop->setVisible(false);
00410 
00411     set->addProperty(prop 
00412         = new KoProperty::Property("primaryKey", QVariant(field->isPrimaryKey(), 4), i18n("Primary Key")));
00413     prop->setIcon("key");
00414 
00415     set->addProperty(
00416         new KoProperty::Property("unique", QVariant(field->isUniqueKey(), 4), i18n("Unique")));
00417 
00418     set->addProperty(
00419         new KoProperty::Property("notNull", QVariant(field->isNotNull(), 4), i18n("Required")));
00420     
00421     set->addProperty(
00422         new KoProperty::Property("allowEmpty", QVariant(!field->isNotEmpty(), 4), i18n("Allow Zero\nSize")));
00423 
00424     set->addProperty(prop 
00425         = new KoProperty::Property("autoIncrement", QVariant(field->isAutoIncrement(), 4), i18n("Autonumber")));
00426     prop->setIcon("autonumber");
00427 
00428     set->addProperty(
00429         new KoProperty::Property("indexed", QVariant(field->isIndexed(), 4), i18n("Indexed")));
00430 
00431     updatePropertiesVisibility(field->type(), *set);
00432 
00433     connect(set, SIGNAL(propertyChanged(KoProperty::Set&, KoProperty::Property&)),
00434         this, SLOT(slotPropertyChanged(KoProperty::Set&, KoProperty::Property&)));
00435 
00436     d->sets->insert(row, set, newOne);
00437     return set;
00438 }
00439 
00440 void KexiAlterTableDialog::updateActions(bool activated)
00441 {
00442     Q_UNUSED(activated);
00444     setAvailable("tablepart_toggle_pkey", propertySet()!=0 && !mainWin()->project()->dbConnection()->isReadOnly());
00445     if (!propertySet())
00446         return;
00447     KoProperty::Set &set = *propertySet();
00448     d->slotTogglePrimaryKeyCalled = true;
00449      d->action_toggle_pkey->setChecked(set["primaryKey"].value().toBool());
00450     d->slotTogglePrimaryKeyCalled = false;
00451 }
00452 
00453 void KexiAlterTableDialog::slotUpdateRowActions(int row)
00454 {
00455     KexiDataTable::slotUpdateRowActions(row);
00456     updateActions();
00457 }
00458 
00459 void KexiAlterTableDialog::slotTogglePrimaryKey()
00460 {
00461     if (d->slotTogglePrimaryKeyCalled)
00462         return;
00463     d->slotTogglePrimaryKeyCalled = true;
00464     if (!propertySet())
00465         return;
00466     KoProperty::Set &set = *propertySet();
00467     bool isSet = !set["primaryKey"].value().toBool();
00468     setPrimaryKey(set, isSet);
00469     d->slotTogglePrimaryKeyCalled = false;
00470 }
00471 
00472 void KexiAlterTableDialog::setPrimaryKey(KoProperty::Set &propertySet, bool set, bool aWasPKey)
00473 {
00474     const bool was_pkey = aWasPKey || propertySet["primaryKey"].value().toBool();
00475     propertySet["primaryKey"] = QVariant(set, 1);
00476     if (&propertySet==this->propertySet()) {
00477         //update action and icon @ column 0 (only if we're changing current property set)
00478         d->action_toggle_pkey->setChecked(set);
00479         if (d->view->selectedItem()) {
00480             //show key in the table
00481             d->view->data()->clearRowEditBuffer();
00482             d->view->data()->updateRowEditBuffer(d->view->selectedItem(), COLUMN_ID_PK, 
00483                 QVariant(set ? "key" : ""));
00484             d->view->data()->saveRowChanges(*d->view->selectedItem(), true);
00485         }
00486         if (was_pkey || set) //change flag only if we're setting pk or really clearing it
00487             d->primaryKeyExists = set;
00488     }
00489 
00490     if (set) {
00491         //primary key is set, remove old pkey if exists
00492         KoProperty::Set *s = 0;
00493         int i;
00494         const int count = (int)d->sets->size();
00495         for (i=0; i<count; i++) {
00496             s = d->sets->at(i);
00497             if (s && s!=&propertySet && (*s)["primaryKey"].value().toBool() && i!=d->view->currentRow())
00498                 break;
00499         }
00500         if (i<count) {//remove
00501             (*s)["autoIncrement"] = QVariant(false, 0);
00502             (*s)["primaryKey"] = QVariant(false, 0);
00503             //remove key from table
00504             d->view->data()->clearRowEditBuffer();
00505             KexiTableItem *item = d->view->itemAt(i);
00506             if (item) {
00507                 d->view->data()->updateRowEditBuffer(item, COLUMN_ID_PK, QVariant());
00508                 d->view->data()->saveRowChanges(*item, true);
00509             }
00510         }
00511         //set unsigned big-integer type
00512 //      d->view->data()->saveRowChanges(*d->view->selectedItem());
00513         d->view->data()->clearRowEditBuffer();
00514         d->view->data()->updateRowEditBuffer(d->view->selectedItem(), COLUMN_ID_TYPE,
00515             QVariant(KexiDB::Field::IntegerGroup-1/*counting from 0*/));
00516 //          QVariant(KexiDB::Field::typeGroupName(KexiDB::Field::IntegerGroup)));
00517         d->view->data()->saveRowChanges(*d->view->selectedItem(), true);
00518 //      propertySet["type"] = KexiDB::Field::typeGroupName(KexiDB::Field::IntegerGroup);
00519 //      propertySet["type"] = (int)KexiDB::Field::IntegerGroup;
00520         propertySet["subType"] = KexiDB::Field::typeString(KexiDB::Field::BigInteger);
00521         propertySet["unsigned"] = QVariant(true,4);
00522     }
00523     updateActions();
00524 }
00525 
00526 /*void KexiAlterTableDialog::slotCellSelected(int, int row)
00527 {
00528     kdDebug() << "KexiAlterTableDialog::slotCellSelected()" << endl;
00529     if(row == m_row)
00530         return;
00531     m_row = row;
00532     propertyBufferSwitched();
00533 }*/
00534 
00535 QString KexiAlterTableDialog::messageForSavingChanges(bool &emptyTable)
00536 {
00537     KexiDB::Connection *conn = mainWin()->project()->dbConnection();
00538     bool ok;
00539     emptyTable = conn->isEmpty( *tempData()->table, ok ) && ok;
00540     return i18n("Do you want to save the design now?")
00541     + ( emptyTable ? QString::null :
00542         (QString("\n\n") + part()->i18nMessage(":additional message before saving design", parentDialog())) );
00543 //      QString("\n\n") + i18n("Note: This table is already filled with data which will be removed.") );
00544 }
00545 
00546 tristate KexiAlterTableDialog::beforeSwitchTo(int mode, bool &dontStore)
00547 {
00548     if (!d->view->acceptRowEdit())
00549         return false;
00550 /*  if (mode==Kexi::DesignViewMode) {
00551         initData();
00552         return true;
00553     }
00554     else */
00555     tristate res = true;
00556     if (mode==Kexi::DataViewMode) {
00557         if (!dirty() && parentDialog()->neverSaved()) {
00558             KMessageBox::sorry(this, i18n("Cannot switch to data view, because table design is empty.\n"
00559                 "First, please create your design.") );
00560             return cancelled;
00561         }
00562 //<temporary>
00563         else if (dirty() && !parentDialog()->neverSaved()) {
00564 //          cancelled = (KMessageBox::No == KMessageBox::questionYesNo(this, i18n("Saving changes for existing table design is not yet supported.\nDo you want to discard your changes now?")));
00565 
00566 //          KexiDB::Connection *conn = mainWin()->project()->dbConnection();
00567             bool emptyTable;
00568             int r = KMessageBox::questionYesNoCancel(this,
00569                 i18n("Saving changes for existing table design is now required.")
00570                 +"\n"+messageForSavingChanges(emptyTable), QString::null,
00571                 KStdGuiItem::save(), KStdGuiItem::discard());
00572             if (r == KMessageBox::Cancel)
00573                 res = cancelled;
00574             else
00575                 res = true;
00576             dontStore = (r!=KMessageBox::Yes);
00577             if (!dontStore)
00578                 d->dontAskOnStoreData = true;
00579 //          if (dontStore)
00580 //              setDirty(false);
00581         }
00582 //</temporary>
00583         //todo
00584         return res;
00585     }
00586     else if (mode==Kexi::TextViewMode) {
00587         //todo
00588     }
00589     return res;
00590 }
00591 
00592 tristate KexiAlterTableDialog::afterSwitchFrom(int mode)
00593 {
00594     if (mode==Kexi::NoViewMode || mode==Kexi::DataViewMode) {
00595         initData();
00596     }
00597     return true;
00598 }
00599 
00600 KoProperty::Set *KexiAlterTableDialog::propertySet()
00601 {
00602     return d->sets ? d->sets->currentPropertySet() : 0;
00603 }
00604 
00605 /*
00606 void KexiAlterTableDialog::removeCurrentPropertySet()
00607 {
00608     const int r = d->view->currentRow();
00609     KoProperty::Set *buf = d->sets.at(r);
00610     if (!buf)
00611         return;
00612     buf->debug();
00613 //  m_currentBufferCleared = true;
00614     d->sets.remove(r);
00615     propertysetswitched();
00616 //  delete buf;
00617 //  m_currentBufferCleared = false;
00618 }
00619 */
00620 
00621 void KexiAlterTableDialog::slotBeforeCellChanged(
00622     KexiTableItem *item, int colnum, QVariant& newValue, KexiDB::ResultInfo* /*result*/)
00623 {
00624 //  kdDebug() << d->view->selectedItem() << " " << item 
00625         //<< " " << d->sets->at( d->view->currentRow() ) << " " << propertySet() << endl;
00626     if (colnum==COLUMN_ID_CAPTION) {//'caption'
00627 //      if (!item->at(1).toString().isEmpty() && item->at(1).isNull()) {
00628         //if 'type' is not filled yet
00629         if (item->at(COLUMN_ID_TYPE).isNull()) {
00630             //auto select 1st row of 'type' column
00631             d->view->data()->updateRowEditBuffer(item, COLUMN_ID_TYPE, QVariant((int)0));
00632         }
00633 
00634         if (propertySet()) {
00635             KoProperty::Set &set = *propertySet();
00636             //update field caption and name
00637             set["caption"] = newValue;
00638             set["name"] = newValue; // "name" prop. is of custom type Identifier, so this assignment 
00639                                     // will automatically convert newValue to an valid identifier
00640         }
00641     }
00642     else if (colnum==COLUMN_ID_TYPE) {//'type'
00643         if (newValue.isNull()) {
00644             //'type' col will be cleared: clear all other columns as well
00645             d->view->data()->updateRowEditBuffer(item, COLUMN_ID_PK, QVariant());
00646             d->view->data()->updateRowEditBuffer(item, COLUMN_ID_CAPTION, QVariant(QString::null));
00647             d->view->data()->updateRowEditBuffer(item, COLUMN_ID_DESC, QVariant());
00648             return;
00649         }
00650 
00651         if (!propertySet())
00652             return;
00653 
00654         KoProperty::Set &set = *propertySet();
00655         //'type' col is changed (existed before)
00656         //-get type group number
00657         KexiDB::Field::TypeGroup fieldTypeGroup;
00658         int i_fieldTypeGroup = newValue.toInt()+1/*counting from 1*/;
00659         if (i_fieldTypeGroup < 1 || i_fieldTypeGroup >
00660 #ifdef KEXI_NO_BLOB_FIELDS
00662             (int)KexiDB::Field::LastTypeGroup-1) //don't show last (BLOB) type
00663 #else
00664             (int)KexiDB::Field::LastTypeGroup)
00665 #endif
00666             return;
00667         fieldTypeGroup = static_cast<KexiDB::Field::TypeGroup>(i_fieldTypeGroup);
00668 
00669         //-get 1st type from this group, and update 'type' property
00670         KexiDB::Field::Type fieldType = KexiDB::defaultTypeForGroup( fieldTypeGroup );
00671         if (fieldType==KexiDB::Field::InvalidType)
00672             fieldType = KexiDB::Field::Text;
00673         set["type"] = (int)fieldType;
00674 //      set["subType"] = KexiDB::Field::typeName(fieldType);
00675         
00676         //-get subtypes for this type: keys (slist) and names (nlist)
00677         QStringList slist, nlist;
00678         getSubTypeListData(fieldTypeGroup, slist, nlist);
00679 
00680         QString subTypeValue;
00681         if (fieldType==KexiDB::Field::BLOB) {
00682             // special case: BLOB type uses "mime-based" subtypes
00683             subTypeValue = slist.first();
00684         }
00685         else {
00686             subTypeValue = KexiDB::Field::typeString(fieldType);
00687         }
00688         KoProperty::Property *subTypeProperty = &set["subType"];
00689 kdDebug() << "++++++++++" << slist << nlist << endl;
00690 
00691         //update subtype list and value
00692         const bool forcePropertySetReload = set["type"].value().toInt() != (int)fieldTypeGroup;
00693         const bool useListData = slist.count() > 1 || fieldType==KexiDB::Field::BLOB;
00694         if (useListData) {
00695             subTypeProperty->setListData( slist, nlist );
00696         }
00697         else {
00698             subTypeProperty->setListData( 0 );
00699         }
00700         if (set["primaryKey"].value().toBool()==true) {
00701             //primary keys require big int, so if selected type is not integer- remove PK
00702             if (fieldTypeGroup != KexiDB::Field::IntegerGroup) {
00703                 d->view->data()->updateRowEditBuffer(item, COLUMN_ID_PK, QVariant());
00704                 set["primaryKey"] = QVariant(false, 1);
00706             }
00707         }
00708         if (useListData)
00709             subTypeProperty->setValue( subTypeValue, false );
00710         if (updatePropertiesVisibility(fieldType, set) || forcePropertySetReload) {
00711             //properties' visiblility changed: refresh prop. set
00712             propertySetReloaded(true);
00713         }
00714     }
00715     else if (colnum==COLUMN_ID_DESC) {//'description'
00716         if (!propertySet())
00717             return;
00718 
00719         //update field desc.
00720         KoProperty::Set &set = *propertySet();
00721         set["description"] = newValue; //item->at(COLUMN_ID_DESC);
00722     }
00723 }
00724 
00725 void KexiAlterTableDialog::slotRowUpdated(KexiTableItem *item)
00726 {
00727     setDirty();
00728 
00729     //-check if the row was empty before updating
00730     //if yes: we want to add a property set for this new row (field)
00731     QString fieldCaption( item->at(COLUMN_ID_CAPTION).toString() );
00732 //  const bool buffer_allowed = !fieldName.isEmpty() && !item->at(1).isNull();
00733     const bool prop_set_allowed = !item->at(COLUMN_ID_TYPE).isNull();
00734 
00735     if (!prop_set_allowed && propertySet()) {
00736         //there is a property set, but it's not allowed - remove it:
00737         d->sets->removeCurrentPropertySet();
00738 
00739         //clear 'type' column:
00740         d->view->data()->clearRowEditBuffer();
00741         d->view->data()->updateRowEditBuffer(d->view->selectedItem(), COLUMN_ID_TYPE, QVariant());
00742         d->view->data()->saveRowChanges(*d->view->selectedItem());
00743 
00744     } else if (prop_set_allowed && !propertySet()) {
00745         //-- create a new field:
00746         KexiDB::Field::TypeGroup fieldTypeGroup = static_cast<KexiDB::Field::TypeGroup>( 
00747             item->at(COLUMN_ID_TYPE).toInt()+1/*counting from 1*/ );
00748         int fieldType = KexiDB::defaultTypeForGroup( fieldTypeGroup );
00749         if (fieldType==0)
00750             return;
00751 
00752         QString description( item->at(COLUMN_ID_DESC).toString() );
00753 
00754 //todo: check uniqueness:
00755         QString fieldName( KexiUtils::string2Identifier(fieldCaption) );
00756 
00757         KexiDB::Field field( //tmp
00758             fieldName,
00759             (KexiDB::Field::Type)fieldType,
00760             KexiDB::Field::NoConstraints,
00761             KexiDB::Field::NoOptions,
00762             /*length*/0,
00763             /*precision*/0,
00764             /*defaultValue*/QVariant(),
00765             fieldCaption,
00766             description,
00767             /*width*/0);
00768 //      m_newTable->addField( field );
00769 
00770         kdDebug() << "KexiAlterTableDialog::slotRowUpdated(): " << field.debugString() << endl;
00771 
00772         //create a new property set:
00773         createPropertySet( d->view->currentRow(), &field, true );
00774 //moved
00775         //add a special property indicating that this is brand new buffer,
00776         //not just changed
00777 //      KoProperty::Property* prop = new KoProperty::Property("newrow", QVariant());
00778 //      prop->setVisible(false);
00779 //      newbuff->addProperty( prop );
00780 
00781         //refresh property editor:
00782         propertySetSwitched();
00783     }
00784 }
00785 
00786 void KexiAlterTableDialog::updateActions()
00787 {
00788     updateActions(false);
00789 }
00790 
00791 void KexiAlterTableDialog::slotPropertyChanged(KoProperty::Set& set, KoProperty::Property& property)
00792 {
00793     const QCString pname = property.name();
00794     kexipluginsdbg << "KexiAlterTableDialog::slotPropertyChanged(): " << pname << " = " << property.value() << endl;
00795     if (pname=="primaryKey" && d->slotPropertyChanged_primaryKey_enabled) {
00796         d->slotPropertyChanged_primaryKey_enabled = false;
00797         if (property.value().toBool()) {
00798             //primary key implies some rules
00799             set["unique"] = QVariant(true,1);
00800             set["notNull"] = QVariant(true,1);
00801             set["allowEmpty"] = QVariant(false,1);
00802             set["indexed"] = QVariant(true,1);
00804             set["autoIncrement"] = QVariant(true,1);
00805         }
00806         else {
00807             set["autoIncrement"] = QVariant(false,1);
00808         }
00809         setPrimaryKey(set, property.value().toBool(), true/*wasPKey*/);
00810         updatePropertiesVisibility(
00811             KexiDB::Field::typeForString( set["subType"].value().toString() ), set);
00812         //properties' visiblility changed: refresh prop. set
00813         propertySetReloaded(true/*preservePrevSelection*/);
00814         d->slotPropertyChanged_primaryKey_enabled = true;
00815     }
00816 //TODO: perhaps show a hint in help panel telling what happens?
00817     else if (property.value().toBool()==false
00818         && (pname=="indexed" || pname=="unique" || pname=="notNull"))
00819     {
00820 //          set["primaryKey"] = QVariant(false,1);
00821         setPrimaryKey(set, false);
00822         if (pname=="notNull")
00823             set["allowEmpty"] = QVariant(true,1);
00824     }
00825     else if (pname=="subType" && d->slotPropertyChanged_subType_enabled) {
00826         d->slotPropertyChanged_subType_enabled = false;
00827         if (set["primaryKey"].value().toBool()==true && property.value().toString()!=KexiDB::Field::typeString(KexiDB::Field::BigInteger)) {
00828             kdDebug() << "INVALID " << property.value().toString() << endl;
00829 //          if (KMessageBox::Yes == KMessageBox::questionYesNo(this, msg,
00830 //              i18n("This field has promary key assigned. Setting autonumber field"),
00831 //              KGuiItem(i18n("Create &Primary Key"), "key"), KStdGuiItem::cancel() ))
00832 
00833         }
00834 //      kdDebug() << property.value().toString() << endl;
00835 //      kdDebug() << set["type"].value() << endl;
00836         if (KexiDB::Field::typeGroup( set["type"].value().toInt() ) == (int)KexiDB::Field::TextGroup) {
00837             updatePropertiesVisibility(KexiDB::Field::typeForString(property.value().toString()), set);
00838             //properties' visiblility changed: refresh prop. set
00839             propertySetReloaded(true);
00840         }
00841         d->slotPropertyChanged_subType_enabled = true;
00842     }
00843     else {//prop==true:
00844         if (property.value().toBool()==true && pname=="autoIncrement") {
00845             if (set["primaryKey"].value().toBool()==false) {//we need PKEY here!
00846                 QString msg = QString("<p>")
00847                     +i18n("Setting autonumber requires primary key to be set for current field.")+"</p>";
00848                 if (d->primaryKeyExists)
00849                     msg += (QString("<p>")+ i18n("Previous primary key will be removed.")+"</p>");
00850                 msg += (QString("<p>")
00851                     +i18n("Do you want to create primary key for current field? "
00852                     "Click \"Cancel\" to cancel setting autonumber.")+"</p>");
00853 
00854                 if (KMessageBox::Yes == KMessageBox::questionYesNo(this, msg,
00855                     i18n("Setting autonumber field"),
00856                     KGuiItem(i18n("Create &Primary Key"), "key"), KStdGuiItem::cancel() ))
00857                 {
00858                     setPrimaryKey(set, true);
00859                 }
00860                 else {
00861                     set["autoIncrement"].setValue( QVariant(false,1), false/*don't save old*/);
00862                 }
00863             }
00864         }
00865     }
00866 }
00867 
00868 void KexiAlterTableDialog::slotAboutToInsertRow(KexiTableItem* /*item*/,
00869     KexiDB::ResultInfo* /*result*/, bool /*repaint*/)
00870 {
00871     setDirty();
00872     //TODO
00873 }
00874 
00875 void KexiAlterTableDialog::slotAboutToDeleteRow(
00876     KexiTableItem& item, KexiDB::ResultInfo* result, bool repaint)
00877 {
00878     Q_UNUSED(result)
00879     Q_UNUSED(repaint)
00880     if (item[COLUMN_ID_PK].toString()=="key")
00881         d->primaryKeyExists = false;
00882 }
00883 
00884 tristate KexiAlterTableDialog::buildSchema(KexiDB::TableSchema &schema)
00885 {
00886     if (!d->view->acceptRowEdit())
00887         return cancelled;
00888 
00889     tristate res = true;
00890     //check for pkey; automatically add a pkey if user wanted
00891     if (!d->primaryKeyExists) {
00892         const int questionRes = KMessageBox::questionYesNoCancel(this,
00893             i18n("<p>Table \"%1\" has no <b>primary key</b> defined.</p>"
00894             "<p>Although a primary key is not required, it is needed "
00895             "for creating relations between database tables. "
00896             "Do you want to add primary key automatically now?</p>"
00897             "<p>If you want to add a primary key by hand, press \"Cancel\" "
00898             "to cancel saving table design.</p>").arg(schema.name()),
00899             QString::null, KGuiItem(i18n("&Add Primary Key"), "key"), KStdGuiItem::no(),
00900                 "autogeneratePrimaryKeysOnTableDesignSaving");
00901         if (questionRes==KMessageBox::Cancel) {
00902             return cancelled;
00903         }
00904         else if (questionRes==KMessageBox::Yes) {
00905             //-find unique name, starting with, "id", "id2", ....
00906             int i=0;
00907             int idIndex = 1; //means "id"
00908             QString pkFieldName("id%1");
00909             QString pkFieldCaption(i18n("Identifier%1", "Id%1"));
00910             while (i<(int)d->sets->size()) {
00911                 KoProperty::Set *set = d->sets->at(i);
00912                 if (set) {
00913                     if ((*set)["name"].value().toString()
00914                         == pkFieldName.arg(idIndex==1?QString::null : QString::number(idIndex))
00915                     || (*set)["caption"].value().toString()
00916                     == pkFieldCaption.arg(idIndex==1?QString::null : QString::number(idIndex)))
00917                     {
00918                         //try next id index
00919                         i = 0;
00920                         idIndex++;
00921                         continue;
00922                     }
00923                 }
00924                 i++;
00925             }
00926             pkFieldName = pkFieldName.arg(idIndex==1?QString::null : QString::number(idIndex));
00927             pkFieldCaption = pkFieldCaption.arg(idIndex==1?QString::null : QString::number(idIndex));
00928             //ok, add PK with such unique name
00929             d->view->insertEmptyRow(0);
00930             d->view->setCursorPosition(0, COLUMN_ID_CAPTION);
00931             d->view->data()->updateRowEditBuffer(d->view->selectedItem(), COLUMN_ID_CAPTION,
00932                 QVariant(pkFieldCaption));
00933             d->view->data()->updateRowEditBuffer(d->view->selectedItem(), COLUMN_ID_TYPE,
00934                 QVariant(KexiDB::Field::IntegerGroup-1/*counting from 0*/));
00935             if (!d->view->data()->saveRowChanges(*d->view->selectedItem(), true)) {
00936                 return cancelled;
00937             }
00938             slotTogglePrimaryKey();
00939         }
00940     }
00941 
00942     //check for duplicates
00943     KoProperty::Set *b = 0;
00944     bool no_fields = true;
00945     int i;
00946     QDict<char> names(101, false);
00947     char dummy;
00948     for (i=0;i<(int)d->sets->size();i++) {
00949         b = d->sets->at(i);
00950         if (b) {
00951             no_fields = false;
00952             const QString name = (*b)["name"].value().toString();
00953             if (name.isEmpty()) {
00954                 d->view->setCursorPosition(i, COLUMN_ID_CAPTION);
00955                 d->view->startEditCurrentCell();
00956                 KMessageBox::information(this, i18n("You should enter field caption.") );
00957                 res = cancelled;
00958                 break;
00959             }
00960             if (names[name]) {
00961                 break;
00962             }
00963             names.insert( name, &dummy ); //remember
00964         }
00965     }
00966     if (res && no_fields) {//no fields added
00967         KMessageBox::sorry(this,
00968             i18n("You have added no fields.\nEvery table should have at least one field.") );
00969         res = cancelled;
00970     }
00971     if (res && b && i<(int)d->sets->size()) {//found a duplicate
00972         d->view->setCursorPosition(i, COLUMN_ID_CAPTION);
00973         d->view->startEditCurrentCell();
00975         KMessageBox::sorry(this,
00976             i18n("You have added \"%1\" field name twice.\nField names cannot be repeated. "
00977             "Correct name of the field.")
00978             .arg((*b)["name"].value().toString()) );
00979         res = cancelled;
00980     }
00981     if (res) {
00982         //for every field, create KexiDB::Field definition
00983         for (i=0;i<(int)d->sets->size();i++) {
00984             KoProperty::Set *s = d->sets->at(i);
00985             if (!s)
00986                 continue;
00987             KoProperty::Set &set = *s;
00988 
00989             kexipluginsdbg << set["subType"].value().toString() << endl;
00990 //          int i_type = set["type"].value().toInt();
00991             QString subTypeString( set["subType"].value().toString() );
00992 /*          if (type == (int)KexiDB::Field::BLOB) {
00994             }
00995             else {
00996                 QString subTypeString = set["subType"].value().toString();
00997                 KexiDB::Field::Type type = KexiDB::Field::typeForString(subTypeString);
00998             }*/
00999             KexiDB::Field::Type type = KexiDB::Field::typeForString(subTypeString);
01000 //          KexiDB::Field::Type type;
01001             if (type <= (int)KexiDB::Field::InvalidType || type > (int)KexiDB::Field::LastType) {//for sanity
01002                 type = KexiDB::Field::Text;
01003                 kexipluginswarn << "KexiAlterTableDialog::buildSchema(): invalid type " << type 
01004                     << ", moving back to Text type" << endl;
01005             }
01006 //          else 
01007 //              type = (KexiDB::Field::Type)i_type;
01008 
01009             uint constraints = 0;
01010             uint options = 0;
01011             if (set["primaryKey"].value().toBool())
01012                 constraints |= KexiDB::Field::PrimaryKey;
01013             if (set["autoIncrement"].value().toBool() && KexiDB::Field::isAutoIncrementAllowed(type))
01014                 constraints |= KexiDB::Field::AutoInc;
01015             if (set["unique"].value().toBool())
01016                 constraints |= KexiDB::Field::Unique;
01017             if (set["notnull"].value().toBool())
01018                 constraints |= KexiDB::Field::NotNull;
01019             if (!set["allowEmpty"].value().toBool())
01020                 constraints |= KexiDB::Field::NotEmpty;
01021 
01022             if (set["unsigned"].value().toBool())
01023                 options |= KexiDB::Field::Unsigned;
01024 
01025     //      int type = set["type"].value().toInt();
01026     //      if (type < 0 || type > (int)KexiDB::Field::LastType)
01027     //          type = KexiDB::Field::Text;
01028 
01029             KexiDB::Field *f = new KexiDB::Field(
01030                 set["name"].value().toString(),
01031                 type,
01032                 constraints,
01033                 options,
01034                 set["length"].value().toInt(),
01035                 set["precision"].value().toInt(),
01036                 set["defaultValue"].value(),
01037                 set["caption"].value().toString(),
01038                 set["description"].value().toString(),
01039                 set["width"].value().toInt()
01040             );
01041             schema.addField(f);
01042         }
01043     }
01044     return res;
01045 }
01046 
01047 KexiDB::SchemaData* KexiAlterTableDialog::storeNewData(const KexiDB::SchemaData& sdata, bool &cancel)
01048 {
01049     if (tempData()->table || m_dialog->schemaData()) //must not be
01050         return 0;
01051 
01052     //create table schema definition
01053     tempData()->table = new KexiDB::TableSchema(sdata.name());
01054     tempData()->table->setName( sdata.name() );
01055     tempData()->table->setCaption( sdata.caption() );
01056     tempData()->table->setDescription( sdata.description() );
01057 
01058     tristate res = buildSchema(*tempData()->table);
01059     cancel = ~res;
01060 
01061     //FINALLY: create table:
01062     if (res) {
01063         //todo
01064         KexiDB::Connection *conn = mainWin()->project()->dbConnection();
01065         res = conn->createTable(tempData()->table);
01066         if (res!=true)
01067             parentDialog()->setStatus(conn, "");
01068     }
01069 
01070     if (res) {
01071         //we've current schema
01072         tempData()->tableSchemaChangedInPreviousView = true;
01073 //not needed; KexiProject emits newItemStored signal //let project know the table is created
01074 //      mainWin()->project()->emitTableCreated(*tempData()->table);
01075     }
01076     else {
01077         delete tempData()->table;
01078         tempData()->table = 0;
01079     }
01080     return tempData()->table;
01081 }
01082 
01083 tristate KexiAlterTableDialog::storeData(bool dontAsk)
01084 {
01085     if (!tempData()->table || !m_dialog->schemaData())
01086         return 0;
01087 
01088     tristate res = true;
01089     if (!d->dontAskOnStoreData && !dontAsk) {
01090         bool emptyTable;
01091         const QString msg = messageForSavingChanges(emptyTable);
01092         if (!emptyTable) {
01093             if (KMessageBox::No == KMessageBox::questionYesNo(this, msg))
01094                 res = cancelled;
01095         }
01096     }
01097     d->dontAskOnStoreData = false; //one-time use
01098     if (~res)
01099         return res;
01100 //      KMessageBox::information(this, i18n("Saving changes for existing table design is not yet supported."));
01101 //      cancel = true;
01102 
01103     KexiDB::TableSchema *newTable = new KexiDB::TableSchema();
01104     //copy schema data
01105     static_cast<KexiDB::SchemaData&>(*newTable) = static_cast<KexiDB::SchemaData&>(*tempData()->table);
01106     res = buildSchema(*newTable);
01107 //  bool ok = buildSchema(*newTable, cancel) && !cancel;
01108 
01109     kdDebug() << "KexiAlterTableDialog::storeData() : BUILD SCHEMA:" << endl;
01110     newTable->debug();
01111 
01112     KexiDB::Connection *conn = mainWin()->project()->dbConnection();
01113     if (res) {
01114         res = KexiTablePart::askForClosingObjectsUsingTableSchema(
01115             this, *conn, *tempData()->table,
01116             i18n("You are about to change the design of table \"%1\" "
01117             "but following objects using this table are opened:")
01118             .arg(tempData()->table->name()));
01119     }
01120     if (res) {
01121         res = conn->alterTable(*tempData()->table, *newTable);
01122         if (!res)
01123             parentDialog()->setStatus(conn, "");
01124     }
01125     if (res) {
01126         //change current schema
01127         tempData()->table = newTable;
01128         tempData()->tableSchemaChangedInPreviousView = true;
01129     }
01130     else {
01131         delete newTable;
01132     }
01133     return res;
01134 }
01135 
01136 KexiTablePart::TempData* KexiAlterTableDialog::tempData() const
01137 {
01138     return static_cast<KexiTablePart::TempData*>(parentDialog()->tempData());
01139 }
01140 
01141 /*void KexiAlterTableDialog::slotAboutToUpdateRow(
01142     KexiTableItem* item, KexiDB::RowEditBuffer* buffer, KexiDB::ResultInfo* result)
01143 {
01144     KexiDB::RowEditBuffer::SimpleMap map = buffer->simpleBuffer();
01145     buffer->debug();
01146 
01147     QVariant old_type = item->at(1);
01148     QVariant *buf_type = buffer->at( d->view->field(1)->name() );
01149 
01150     //check if there is a type specified
01151 //  if ((old_type.isNull() && !buf_type) || (buf_type && buf_type->isNull())) {
01152         //kdDebug() << "err" << endl;
01153     //}
01154 //  allow = true;
01155 //  m_dirty = m_dirty | result->success;
01156 }*/
01157 
01158 
01159 
01160 #include "kexialtertabledialog.moc"
01161 
KDE Home | KDE Accessibility Home | Description of Access Keys