kexi

kexitabledesignerview_p.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004-2007 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 "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     // We need ALL the commands because we'll collect reuse their 
00060     // data before performing alter table, so set that to the maximum, 
00061     // as KCommandHistory has default = 50.
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; //remember because we'll change list data soon
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; //remember
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; //restore
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     //if there is no more than 1 subType name or it's a PK: hide the property
00211     visible = (prop->listData() && prop->listData()->keys.count() > 1 /*disabled || isObjectTypeGroup*/)
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; // used only for BLOBs
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 //              prop->setVisible( visible );
00228         //update the length when it makes sense
00229         const int lengthToSet = visible ? KexiDB::Field::defaultTextLength() : 0;
00230         setPropertyValueIfNeeded( set, "length", lengthToSet, 
00231             commandGroup, false, false  );
00232 //      if (lengthToSet != prop->value().toInt())
00233 //          prop->setValue( lengthToSet, false );
00234 //              changed = true;
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     //show/hide icon in the table
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"
KDE Home | KDE Accessibility Home | Description of Access Keys