00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexitabledesignerview_p.h"
00021 #include "kexitabledesignerview.h"
00022
00023 #include <qlayout.h>
00024 #include <qlabel.h>
00025 #include <qsplitter.h>
00026
00027 #include <kiconloader.h>
00028 #include <kdebug.h>
00029 #include <klocale.h>
00030 #include <kaction.h>
00031 #include <kpopupmenu.h>
00032 #include <kmessagebox.h>
00033
00034 #include <koproperty/set.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 <kexiutils/utils.h>
00048 #include <kexidialogbase.h>
00049 #include <kexitableview.h>
00050 #include "kexitabledesignercommands.h"
00051
00052 using namespace KexiTableDesignerCommands;
00053
00054
00055
00056 CommandHistory::CommandHistory(KActionCollection *actionCollection, bool withMenus)
00057 : KCommandHistory(actionCollection, withMenus)
00058 {
00059
00060
00061
00062 setUndoLimit(INT_MAX);
00063 setRedoLimit(INT_MAX);
00064 }
00065
00066 void CommandHistory::addCommand(KCommand *command, bool execute)
00067 {
00068 KCommandHistory::addCommand(command, execute);
00069 m_commandsToUndo.append(command);
00070 }
00071
00072 void CommandHistory::undo()
00073 {
00074 if (!m_commandsToUndo.isEmpty()) {
00075 KCommand * cmd = m_commandsToUndo.take( m_commandsToUndo.count()-1 );
00076 m_commandsToRedo.append( cmd );
00077 }
00078 KCommandHistory::undo();
00079 }
00080
00081 void CommandHistory::redo()
00082 {
00083 if (!m_commandsToRedo.isEmpty()) {
00084 KCommand * cmd = m_commandsToRedo.take( m_commandsToRedo.count()-1 );
00085 m_commandsToUndo.append( cmd );
00086 }
00087 KCommandHistory::redo();
00088 }
00089
00090 void CommandHistory::clear() {
00091 KCommandHistory::clear(); m_commandsToUndo.clear();
00092 }
00093
00094
00095
00096 KexiTableDesignerViewPrivate::KexiTableDesignerViewPrivate(KexiTableDesignerView* aDesignerView)
00097 : designerView(aDesignerView)
00098 , sets(0)
00099 , uniqueIdCounter(0)
00100 , dontAskOnStoreData(false)
00101 , slotTogglePrimaryKeyCalled(false)
00102 , primaryKeyExists(false)
00103 , slotPropertyChanged_primaryKey_enabled(true)
00104 , slotPropertyChanged_subType_enabled(true)
00105 , addHistoryCommand_in_slotPropertyChanged_enabled(true)
00106 , addHistoryCommand_in_slotRowUpdated_enabled(true)
00107 , addHistoryCommand_in_slotAboutToDeleteRow_enabled(true)
00108 , addHistoryCommand_in_slotRowInserted_enabled(true)
00109 , slotBeforeCellChanged_enabled(true)
00110 , tempStoreDataUsingRealAlterTable(false)
00111 {
00112 historyActionCollection = new KActionCollection((QWidget*)0,"");
00113 history = new CommandHistory(historyActionCollection, true);
00114
00115 internalPropertyNames.insert("subType",(char*)1);
00116 internalPropertyNames.insert("uid",(char*)1);
00117 internalPropertyNames.insert("newrow",(char*)1);
00118 internalPropertyNames.insert("rowSource",(char*)1);
00119 internalPropertyNames.insert("rowSourceType",(char*)1);
00120 internalPropertyNames.insert("boundColumn",(char*)1);
00121 internalPropertyNames.insert("visibleColumn",(char*)1);
00122 }
00123
00124 KexiTableDesignerViewPrivate::~KexiTableDesignerViewPrivate() {
00125 delete sets;
00126 delete historyActionCollection;
00127 delete history;
00128 }
00129
00130 int KexiTableDesignerViewPrivate::generateUniqueId()
00131 {
00132 return ++uniqueIdCounter;
00133 }
00134
00135 void KexiTableDesignerViewPrivate::setPropertyValueIfNeeded(
00136 const KoProperty::Set& set, const QCString& propertyName,
00137 const QVariant& newValue, const QVariant& oldValue, CommandGroup* commandGroup,
00138 bool forceAddCommand, bool rememberOldValue,
00139 QStringList* const slist, QStringList* const nlist)
00140 {
00141 KoProperty::Property& property = set[propertyName];
00142
00143 KoProperty::Property::ListData *oldListData = property.listData() ?
00144 new KoProperty::Property::ListData(*property.listData()) : 0;
00145 if (slist && nlist) {
00146 if (slist->isEmpty() || nlist->isEmpty()) {
00147 property.setListData(0);
00148 }
00149 else {
00150 property.setListData(*slist, *nlist);
00151 }
00152 }
00153 if (oldValue.type() == newValue.type()
00154 && (oldValue == newValue || (!oldValue.isValid() && !newValue.isValid()))
00155 && !forceAddCommand)
00156 {
00157 return;
00158 }
00159
00160 const bool prev_addHistoryCommand_in_slotPropertyChanged_enabled
00161 = addHistoryCommand_in_slotPropertyChanged_enabled;
00162 addHistoryCommand_in_slotPropertyChanged_enabled = false;
00163 if (property.value() != newValue)
00164 property.setValue( newValue, rememberOldValue );
00165 if (commandGroup) {
00166 commandGroup->addCommand(
00167 new ChangeFieldPropertyCommand( designerView, set, propertyName, oldValue, newValue,
00168 oldListData, property.listData()) );
00169 }
00170 delete oldListData;
00171 addHistoryCommand_in_slotPropertyChanged_enabled
00172 = prev_addHistoryCommand_in_slotPropertyChanged_enabled;
00173 }
00174
00175 void KexiTableDesignerViewPrivate::setPropertyValueIfNeeded(
00176 const KoProperty::Set& set, const QCString& propertyName,
00177 const QVariant& newValue, CommandGroup* commandGroup,
00178 bool forceAddCommand, bool rememberOldValue,
00179 QStringList* const slist, QStringList* const nlist)
00180 {
00181 KoProperty::Property& property = set[propertyName];
00182 QVariant oldValue( property.value() );
00183 setPropertyValueIfNeeded( set, propertyName, newValue, property.value(),
00184 commandGroup, forceAddCommand, rememberOldValue, slist, nlist);
00185 }
00186
00187 void KexiTableDesignerViewPrivate::setVisibilityIfNeeded( const KoProperty::Set& set, KoProperty::Property* prop,
00188 bool visible, bool &changed, CommandGroup *commandGroup )
00189 {
00190 if (prop->isVisible() != visible) {
00191 if (commandGroup) {
00192 commandGroup->addCommand(
00193 new ChangePropertyVisibilityCommand( designerView, set, prop->name(), visible ) );
00194 }
00195 prop->setVisible( visible );
00196 changed = true;
00197 }
00198 }
00199
00200 bool KexiTableDesignerViewPrivate::updatePropertiesVisibility(KexiDB::Field::Type fieldType, KoProperty::Set &set,
00201 CommandGroup *commandGroup)
00202 {
00203 bool changed = false;
00204 KoProperty::Property *prop;
00205 bool visible;
00206
00207 prop = &set["subType"];
00208 kexipluginsdbg << "subType=" << prop->value().toInt() << " type=" << set["type"].value().toInt()<< endl;
00209
00210
00211 visible = (prop->listData() && prop->listData()->keys.count() > 1 )
00212 && set["primaryKey"].value().toBool()==false;
00213 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00214
00215 prop = &set["objectType"];
00216 const bool isObjectTypeGroup = set["type"].value().toInt() == (int)KexiDB::Field::BLOB;
00217 visible = isObjectTypeGroup;
00218 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00219
00220 prop = &set["unsigned"];
00221 visible = KexiDB::Field::isNumericType(fieldType);
00222 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00223
00224 prop = &set["length"];
00225 visible = (fieldType == KexiDB::Field::Text);
00226 if (prop->isVisible()!=visible) {
00227
00228
00229 const int lengthToSet = visible ? KexiDB::Field::defaultTextLength() : 0;
00230 setPropertyValueIfNeeded( set, "length", lengthToSet,
00231 commandGroup, false, false );
00232
00233
00234
00235 }
00236 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00237 #ifndef KEXI_NO_UNFINISHED
00238 prop = &set["precision"];
00239 visible = KexiDB::Field::isFPNumericType(fieldType);
00240 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00241 #endif
00242 prop = &set["visibleDecimalPlaces"];
00243 visible = KexiDB::supportsVisibleDecimalPlacesProperty(fieldType);
00244 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00245
00246 prop = &set["unique"];
00247 visible = fieldType != KexiDB::Field::BLOB;
00248 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00249
00250 prop = &set["indexed"];
00251 visible = fieldType != KexiDB::Field::BLOB;
00252 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00253
00254 prop = &set["allowEmpty"];
00255 visible = KexiDB::Field::hasEmptyProperty(fieldType);
00256 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00257
00258 prop = &set["autoIncrement"];
00259 visible = KexiDB::Field::isAutoIncrementAllowed(fieldType);
00260 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00261
00263 #ifdef KEXI_NO_UNFINISHED
00264 prop = &set["defaultValue"];
00265 visible = !isObjectTypeGroup;
00266 setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
00267 #endif
00268
00269 return changed;
00270 }
00271
00272 QString KexiTableDesignerViewPrivate::messageForSavingChanges(bool &emptyTable, bool skipWarning)
00273 {
00274 KexiDB::Connection *conn = designerView->mainWin()->project()->dbConnection();
00275 bool ok;
00276 emptyTable = conn->isEmpty( *designerView->tempData()->table, ok ) && ok;
00277 return i18n("Do you want to save the design now?")
00278 + ( (emptyTable || skipWarning) ? QString::null :
00279 (QString("\n\n") + designerView->part()->i18nMessage(":additional message before saving design",
00280 designerView->parentDialog())) );
00281 }
00282
00283 void KexiTableDesignerViewPrivate::updateIconForItem(KexiTableItem &item, KoProperty::Set& set)
00284 {
00285 QVariant icon;
00286 if (!set["rowSource"].value().toString().isEmpty() && !set["rowSourceType"].value().toString().isEmpty())
00287 icon = "combo";
00288
00289 view->data()->clearRowEditBuffer();
00290 view->data()->updateRowEditBuffer(&item, COLUMN_ID_ICON, icon);
00291 view->data()->saveRowChanges(item, true);
00292 }
00293
00294 #include "kexitabledesignerview_p.moc"