You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/kexi/plugins/tables/kexitabledesignerview_p.cpp

295 lines
10 KiB

/* This file is part of the KDE project
Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kexitabledesignerview_p.h"
#include "kexitabledesignerview.h"
#include <qlayout.h>
#include <qlabel.h>
#include <qsplitter.h>
#include <kiconloader.h>
#include <kdebug.h>
#include <klocale.h>
#include <kaction.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <koproperty/set.h>
#include <kexidb/cursor.h>
#include <kexidb/tableschema.h>
#include <kexidb/connection.h>
#include <kexidb/utils.h>
#include <kexidb/roweditbuffer.h>
#include <kexidb/error.h>
#include <kexiutils/identifier.h>
#include <kexiproject.h>
#include <keximainwindow.h>
#include <widget/tableview/kexidataawarepropertyset.h>
#include <widget/kexicustompropertyfactory.h>
#include <kexiutils/utils.h>
#include <kexidialogbase.h>
#include <kexitableview.h>
#include "kexitabledesignercommands.h"
using namespace KexiTableDesignerCommands;
//----------------------------------------------
CommandHistory::CommandHistory(KActionCollection *actionCollection, bool withMenus)
: KCommandHistory(actionCollection, withMenus)
{
// We need ALL the commands because we'll collect reuse their
// data before performing alter table, so set that to the maximum,
// as KCommandHistory has default = 50.
setUndoLimit(INT_MAX);
setRedoLimit(INT_MAX);
}
void CommandHistory::addCommand(KCommand *command, bool execute)
{
KCommandHistory::addCommand(command, execute);
m_commandsToUndo.append(command);
}
void CommandHistory::undo()
{
if (!m_commandsToUndo.isEmpty()) {
KCommand * cmd = m_commandsToUndo.take( m_commandsToUndo.count()-1 );
m_commandsToRedo.append( cmd );
}
KCommandHistory::undo();
}
void CommandHistory::redo()
{
if (!m_commandsToRedo.isEmpty()) {
KCommand * cmd = m_commandsToRedo.take( m_commandsToRedo.count()-1 );
m_commandsToUndo.append( cmd );
}
KCommandHistory::redo();
}
void CommandHistory::clear() {
KCommandHistory::clear(); m_commandsToUndo.clear();
}
//----------------------------------------------
KexiTableDesignerViewPrivate::KexiTableDesignerViewPrivate(KexiTableDesignerView* aDesignerView)
: designerView(aDesignerView)
, sets(0)
, uniqueIdCounter(0)
, dontAskOnStoreData(false)
, slotTogglePrimaryKeyCalled(false)
, primaryKeyExists(false)
, slotPropertyChanged_primaryKey_enabled(true)
, slotPropertyChanged_subType_enabled(true)
, addHistoryCommand_in_slotPropertyChanged_enabled(true)
, addHistoryCommand_in_slotRowUpdated_enabled(true)
, addHistoryCommand_in_slotAboutToDeleteRow_enabled(true)
, addHistoryCommand_in_slotRowInserted_enabled(true)
, slotBeforeCellChanged_enabled(true)
, tempStoreDataUsingRealAlterTable(false)
{
historyActionCollection = new KActionCollection((QWidget*)0,"");
history = new CommandHistory(historyActionCollection, true);
internalPropertyNames.insert("subType",(char*)1);
internalPropertyNames.insert("uid",(char*)1);
internalPropertyNames.insert("newrow",(char*)1);
internalPropertyNames.insert("rowSource",(char*)1);
internalPropertyNames.insert("rowSourceType",(char*)1);
internalPropertyNames.insert("boundColumn",(char*)1);
internalPropertyNames.insert("visibleColumn",(char*)1);
}
KexiTableDesignerViewPrivate::~KexiTableDesignerViewPrivate() {
delete sets;
delete historyActionCollection;
delete history;
}
int KexiTableDesignerViewPrivate::generateUniqueId()
{
return ++uniqueIdCounter;
}
void KexiTableDesignerViewPrivate::setPropertyValueIfNeeded(
const KoProperty::Set& set, const QCString& propertyName,
const QVariant& newValue, const QVariant& oldValue, CommandGroup* commandGroup,
bool forceAddCommand, bool rememberOldValue,
QStringList* const slist, QStringList* const nlist)
{
KoProperty::Property& property = set[propertyName];
KoProperty::Property::ListData *oldListData = property.listData() ?
new KoProperty::Property::ListData(*property.listData()) : 0; //remember because we'll change list data soon
if (slist && nlist) {
if (slist->isEmpty() || nlist->isEmpty()) {
property.setListData(0);
}
else {
property.setListData(*slist, *nlist);
}
}
if (oldValue.type() == newValue.type()
&& (oldValue == newValue || (!oldValue.isValid() && !newValue.isValid()))
&& !forceAddCommand)
{
return;
}
const bool prev_addHistoryCommand_in_slotPropertyChanged_enabled
= addHistoryCommand_in_slotPropertyChanged_enabled; //remember
addHistoryCommand_in_slotPropertyChanged_enabled = false;
if (property.value() != newValue)
property.setValue( newValue, rememberOldValue );
if (commandGroup) {
commandGroup->addCommand(
new ChangeFieldPropertyCommand( designerView, set, propertyName, oldValue, newValue,
oldListData, property.listData()) );
}
delete oldListData;
addHistoryCommand_in_slotPropertyChanged_enabled
= prev_addHistoryCommand_in_slotPropertyChanged_enabled; //restore
}
void KexiTableDesignerViewPrivate::setPropertyValueIfNeeded(
const KoProperty::Set& set, const QCString& propertyName,
const QVariant& newValue, CommandGroup* commandGroup,
bool forceAddCommand, bool rememberOldValue,
QStringList* const slist, QStringList* const nlist)
{
KoProperty::Property& property = set[propertyName];
QVariant oldValue( property.value() );
setPropertyValueIfNeeded( set, propertyName, newValue, property.value(),
commandGroup, forceAddCommand, rememberOldValue, slist, nlist);
}
void KexiTableDesignerViewPrivate::setVisibilityIfNeeded( const KoProperty::Set& set, KoProperty::Property* prop,
bool visible, bool &changed, CommandGroup *commandGroup )
{
if (prop->isVisible() != visible) {
if (commandGroup) {
commandGroup->addCommand(
new ChangePropertyVisibilityCommand( designerView, set, prop->name(), visible ) );
}
prop->setVisible( visible );
changed = true;
}
}
bool KexiTableDesignerViewPrivate::updatePropertiesVisibility(KexiDB::Field::Type fieldType, KoProperty::Set &set,
CommandGroup *commandGroup)
{
bool changed = false;
KoProperty::Property *prop;
bool visible;
prop = &set["subType"];
kexipluginsdbg << "subType=" << prop->value().toInt() << " type=" << set["type"].value().toInt()<< endl;
//if there is no more than 1 subType name or it's a PK: hide the property
visible = (prop->listData() && prop->listData()->keys.count() > 1 /*disabled || isObjectTypeGroup*/)
&& set["primaryKey"].value().toBool()==false;
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["objectType"];
const bool isObjectTypeGroup = set["type"].value().toInt() == (int)KexiDB::Field::BLOB; // used only for BLOBs
visible = isObjectTypeGroup;
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["unsigned"];
visible = KexiDB::Field::isNumericType(fieldType);
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["length"];
visible = (fieldType == KexiDB::Field::Text);
if (prop->isVisible()!=visible) {
// prop->setVisible( visible );
//update the length when it makes sense
const int lengthToSet = visible ? KexiDB::Field::defaultTextLength() : 0;
setPropertyValueIfNeeded( set, "length", lengthToSet,
commandGroup, false, false /*!rememberOldValue*/ );
// if (lengthToSet != prop->value().toInt())
// prop->setValue( lengthToSet, false );
// changed = true;
}
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
#ifndef KEXI_NO_UNFINISHED
prop = &set["precision"];
visible = KexiDB::Field::isFPNumericType(fieldType);
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
#endif
prop = &set["visibleDecimalPlaces"];
visible = KexiDB::supportsVisibleDecimalPlacesProperty(fieldType);
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["unique"];
visible = fieldType != KexiDB::Field::BLOB;
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["indexed"];
visible = fieldType != KexiDB::Field::BLOB;
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["allowEmpty"];
visible = KexiDB::Field::hasEmptyProperty(fieldType);
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
prop = &set["autoIncrement"];
visible = KexiDB::Field::isAutoIncrementAllowed(fieldType);
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
//! @todo remove this when BLOB supports default value
#ifdef KEXI_NO_UNFINISHED
prop = &set["defaultValue"];
visible = !isObjectTypeGroup;
setVisibilityIfNeeded( set, prop, visible, changed, commandGroup );
#endif
return changed;
}
QString KexiTableDesignerViewPrivate::messageForSavingChanges(bool &emptyTable, bool skipWarning)
{
KexiDB::Connection *conn = designerView->mainWin()->project()->dbConnection();
bool ok;
emptyTable = conn->isEmpty( *designerView->tempData()->table, ok ) && ok;
return i18n("Do you want to save the design now?")
+ ( (emptyTable || skipWarning) ? QString::null :
(QString("\n\n") + designerView->part()->i18nMessage(":additional message before saving design",
designerView->parentDialog())) );
}
void KexiTableDesignerViewPrivate::updateIconForItem(KexiTableItem &item, KoProperty::Set& set)
{
QVariant icon;
if (!set["rowSource"].value().toString().isEmpty() && !set["rowSourceType"].value().toString().isEmpty())
icon = "combo";
//show/hide icon in the table
view->data()->clearRowEditBuffer();
view->data()->updateRowEditBuffer(&item, COLUMN_ID_ICON, icon);
view->data()->saveRowChanges(item, true);
}
#include "kexitabledesignerview_p.moc"