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