|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
|
|
|
|
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 "kexidblineedit.h"
|
|
|
|
#include "kexidbautofield.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <knumvalidator.h>
|
|
|
|
#include <kdatetbl.h>
|
|
|
|
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
|
|
|
|
#include <kexiutils/utils.h>
|
|
|
|
#include <kexidb/queryschema.h>
|
|
|
|
#include <kexidb/fieldvalidator.h>
|
|
|
|
#include <kexiutils/utils.h>
|
|
|
|
|
|
|
|
//! @todo reenable as an app aption
|
|
|
|
//#define USE_KLineEdit_setReadOnly
|
|
|
|
|
|
|
|
//! @internal A validator used for read only flag to disable editing
|
|
|
|
class KexiDBLineEdit_ReadOnlyValidator : public TQValidator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KexiDBLineEdit_ReadOnlyValidator( TQObject * parent )
|
|
|
|
: TQValidator(parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
~KexiDBLineEdit_ReadOnlyValidator() {}
|
|
|
|
virtual State validate( TQString &, int & ) const { return Invalid; }
|
|
|
|
};
|
|
|
|
|
|
|
|
//-----
|
|
|
|
|
|
|
|
KexiDBLineEdit::KexiDBLineEdit(TQWidget *parent, const char *name)
|
|
|
|
: KLineEdit(parent, name)
|
|
|
|
, KexiDBTextWidgetInterface()
|
|
|
|
, KexiFormDataItemInterface()
|
|
|
|
//moved , m_dateFormatter(0)
|
|
|
|
//moved , m_timeFormatter(0)
|
|
|
|
, m_menuExtender(TQT_TQOBJECT(this), this)
|
|
|
|
, m_internalReadOnly(false)
|
|
|
|
, m_slotTextChanged_enabled(true)
|
|
|
|
{
|
|
|
|
#ifdef USE_KLineEdit_setReadOnly
|
|
|
|
//! @todo reenable as an app aption
|
|
|
|
TQPalette p(widget->palette());
|
|
|
|
p.setColor( lighterGrayBackgroundColor(palette()) );
|
|
|
|
widget->setPalette(p);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotTextChanged(const TQString&)));
|
|
|
|
}
|
|
|
|
|
|
|
|
KexiDBLineEdit::~KexiDBLineEdit()
|
|
|
|
{
|
|
|
|
//moved delete m_dateFormatter;
|
|
|
|
//moved delete m_timeFormatter;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::setInvalidState( const TQString& displayText )
|
|
|
|
{
|
|
|
|
KLineEdit::setReadOnly(true);
|
|
|
|
//! @todo move this to KexiDataItemInterface::setInvalidStateInternal() ?
|
|
|
|
if (focusPolicy() & TQ_TabFocus)
|
|
|
|
setFocusPolicy(TQ_ClickFocus);
|
|
|
|
setText(displayText);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::setValueInternal(const TQVariant& add, bool removeOld)
|
|
|
|
{
|
|
|
|
#if 0 //moved to KexiTextFormatter
|
|
|
|
TQVariant value;
|
|
|
|
if (removeOld)
|
|
|
|
value = add;
|
|
|
|
else {
|
|
|
|
if (add.toString().isEmpty())
|
|
|
|
value = m_origValue;
|
|
|
|
else
|
|
|
|
value = m_origValue.toString() + add.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_columnInfo) {
|
|
|
|
const KexiDB::Field::Type t = m_columnInfo->field->type();
|
|
|
|
if (t == KexiDB::Field::Boolean) {
|
|
|
|
//! @todo temporary solution for booleans!
|
|
|
|
setText( value.toBool() ? "1" : "0" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (t == KexiDB::Field::Date) {
|
|
|
|
setText( dateFormatter()->dateToString( value.toString().isEmpty() ? TQDate() : value.toDate() ) );
|
|
|
|
setCursorPosition(0); //ok?
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (t == KexiDB::Field::Time) {
|
|
|
|
setText(
|
|
|
|
timeFormatter()->timeToString(
|
|
|
|
//hack to avoid converting null variant to valid TQTime(0,0,0)
|
|
|
|
value.toString().isEmpty() ? value.toTime() : TQTime(99,0,0)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
setCursorPosition(0); //ok?
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (t == KexiDB::Field::DateTime) {
|
|
|
|
if (value.toString().isEmpty() ) {
|
|
|
|
setText( TQString() );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setText(
|
|
|
|
dateFormatter()->dateToString( value.toDateTime().date() ) + " " +
|
|
|
|
timeFormatter()->timeToString( value.toDateTime().time() )
|
|
|
|
);
|
|
|
|
}
|
|
|
|
setCursorPosition(0); //ok?
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
m_slotTextChanged_enabled = false;
|
|
|
|
setText( m_textFormatter.valueToText(removeOld ? TQVariant() : m_origValue, add.toString()) );
|
|
|
|
// setText( value.toString() );
|
|
|
|
setCursorPosition(0); //ok?
|
|
|
|
m_slotTextChanged_enabled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQVariant KexiDBLineEdit::value()
|
|
|
|
{
|
|
|
|
return m_textFormatter.textToValue( text() );
|
|
|
|
#if 0 // moved to KexiTextFormatter
|
|
|
|
if (! m_columnInfo)
|
|
|
|
return TQVariant();
|
|
|
|
const KexiDB::Field::Type t = m_columnInfo->field->type();
|
|
|
|
switch (t) {
|
|
|
|
case KexiDB::Field::Text:
|
|
|
|
case KexiDB::Field::LongText:
|
|
|
|
return text();
|
|
|
|
case KexiDB::Field::Byte:
|
|
|
|
case KexiDB::Field::ShortInteger:
|
|
|
|
return text().toShort();
|
|
|
|
//! @todo uint, etc?
|
|
|
|
case KexiDB::Field::Integer:
|
|
|
|
return text().toInt();
|
|
|
|
case KexiDB::Field::BigInteger:
|
|
|
|
return text().toLongLong();
|
|
|
|
case KexiDB::Field::Boolean:
|
|
|
|
//! @todo temporary solution for booleans!
|
|
|
|
return text() == "1" ? TQVariant(true,1) : TQVariant(false,0);
|
|
|
|
case KexiDB::Field::Date:
|
|
|
|
return dateFormatter()->stringToVariant( text() );
|
|
|
|
case KexiDB::Field::Time:
|
|
|
|
return timeFormatter()->stringToVariant( text() );
|
|
|
|
case KexiDB::Field::DateTime:
|
|
|
|
return stringToDateTime(*dateFormatter(), *timeFormatter(), text());
|
|
|
|
case KexiDB::Field::Float:
|
|
|
|
return text().toFloat();
|
|
|
|
case KexiDB::Field::Double:
|
|
|
|
return text().toDouble();
|
|
|
|
default:
|
|
|
|
return TQVariant();
|
|
|
|
}
|
|
|
|
//! @todo more data types!
|
|
|
|
return text();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::slotTextChanged(const TQString&)
|
|
|
|
{
|
|
|
|
if (!m_slotTextChanged_enabled)
|
|
|
|
return;
|
|
|
|
signalValueChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::valueIsNull()
|
|
|
|
{
|
|
|
|
return valueIsEmpty(); //ok??? text().isNull();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::valueIsEmpty()
|
|
|
|
{
|
|
|
|
return m_textFormatter.valueIsEmpty( text() );
|
|
|
|
#if 0 // moved to KexiTextFormatter
|
|
|
|
if (text().isEmpty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (m_columnInfo) {
|
|
|
|
const KexiDB::Field::Type t = m_columnInfo->field->type();
|
|
|
|
if (t == KexiDB::Field::Date || )
|
|
|
|
return dateFormatter()->isEmpty( text() );
|
|
|
|
else if (t == KexiDB::Field::Time)
|
|
|
|
return timeFormatter()->isEmpty( text() );
|
|
|
|
else if (t == KexiDB::Field::Time)
|
|
|
|
return dateTimeIsEmpty( *dateFormatter(), *timeFormatter(), text() );
|
|
|
|
}
|
|
|
|
|
|
|
|
//! @todo
|
|
|
|
return text().isEmpty();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::valueIsValid()
|
|
|
|
{
|
|
|
|
return m_textFormatter.valueIsValid( text() );
|
|
|
|
#if 0 // moved to KexiTextFormatter
|
|
|
|
if (!m_columnInfo)
|
|
|
|
return true;
|
|
|
|
//! @todo fix for fields with "required" property = true
|
|
|
|
if (valueIsEmpty()/*ok?*/)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const KexiDB::Field::Type t = m_columnInfo->field->type();
|
|
|
|
if (t == KexiDB::Field::Date)
|
|
|
|
return dateFormatter()->stringToVariant( text() ).isValid();
|
|
|
|
else if (t == KexiDB::Field::Time)
|
|
|
|
return timeFormatter()->stringToVariant( text() ).isValid();
|
|
|
|
else if (t == KexiDB::Field::DateTime)
|
|
|
|
return dateTimeIsValid( *dateFormatter(), *timeFormatter(), text() );
|
|
|
|
|
|
|
|
//! @todo
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::isReadOnly() const
|
|
|
|
{
|
|
|
|
return m_internalReadOnly;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::setReadOnly( bool readOnly )
|
|
|
|
{
|
|
|
|
#ifdef USE_KLineEdit_setReadOnly
|
|
|
|
//! @todo reenable as an app aption
|
|
|
|
return KLineEdit::setReadOnly( readOnly );
|
|
|
|
#else
|
|
|
|
m_internalReadOnly = readOnly;
|
|
|
|
if (m_internalReadOnly) {
|
|
|
|
m_readWriteValidator = validator();
|
|
|
|
if (!m_readOnlyValidator)
|
|
|
|
m_readOnlyValidator = new KexiDBLineEdit_ReadOnlyValidator(TQT_TQOBJECT(this));
|
|
|
|
setValidator( m_readOnlyValidator );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//revert to r/w validator
|
|
|
|
setValidator( m_readWriteValidator );
|
|
|
|
}
|
|
|
|
m_menuExtender.updatePopupMenuActions();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPopupMenu * KexiDBLineEdit::createPopupMenu()
|
|
|
|
{
|
|
|
|
TQPopupMenu *contextMenu = KLineEdit::createPopupMenu();
|
|
|
|
m_menuExtender.createTitle(contextMenu);
|
|
|
|
return contextMenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQWidget* KexiDBLineEdit::widget()
|
|
|
|
{
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::cursorAtStart()
|
|
|
|
{
|
|
|
|
return cursorPosition()==0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::cursorAtEnd()
|
|
|
|
{
|
|
|
|
return cursorPosition()==(int)text().length();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::clear()
|
|
|
|
{
|
|
|
|
if (!m_internalReadOnly)
|
|
|
|
KLineEdit::clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KexiDBLineEdit::setColumnInfo(KexiDB::QueryColumnInfo* cinfo)
|
|
|
|
{
|
|
|
|
KexiFormDataItemInterface::setColumnInfo(cinfo);
|
|
|
|
m_textFormatter.setField( cinfo ? cinfo->field : 0 );
|
|
|
|
|
|
|
|
if (!cinfo)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//! @todo handle input mask (via TQLineEdit::setInputMask()) using a special KexiDB::FieldInputMask class
|
|
|
|
setValidator( new KexiDB::FieldValidator(*cinfo->field, this) );
|
|
|
|
|
|
|
|
#if 0 // moved to KexiTextFormatter
|
|
|
|
if (t==KexiDB::Field::Date) {
|
|
|
|
//! @todo use KDateWidget?
|
|
|
|
setInputMask( dateFormatter()->inputMask() );
|
|
|
|
}
|
|
|
|
else if (t==KexiDB::Field::Time) {
|
|
|
|
//! @todo use KTimeWidget
|
|
|
|
// setInputMask("00:00:00");
|
|
|
|
setInputMask( timeFormatter()->inputMask() );
|
|
|
|
}
|
|
|
|
else if (t==KexiDB::Field::DateTime) {
|
|
|
|
setInputMask(
|
|
|
|
dateTimeInputMask( *dateFormatter(), *timeFormatter() ) );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
const TQString inputMask( m_textFormatter.inputMask() );
|
|
|
|
if (!inputMask.isEmpty())
|
|
|
|
setInputMask( inputMask );
|
|
|
|
|
|
|
|
KexiDBTextWidgetInterface::setColumnInfo(cinfo, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*todo
|
|
|
|
void KexiDBLineEdit::paint( TQPainter *p )
|
|
|
|
{
|
|
|
|
KexiDBTextWidgetInterface::paint( this, &p, text().isEmpty(), alignment(), hasFocus() );
|
|
|
|
}*/
|
|
|
|
|
|
|
|
void KexiDBLineEdit::paintEvent ( TQPaintEvent *pe )
|
|
|
|
{
|
|
|
|
KLineEdit::paintEvent( pe );
|
|
|
|
TQPainter p(this);
|
|
|
|
KexiDBTextWidgetInterface::paint( this, &p, text().isEmpty(), alignment(), hasFocus() );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::event( TQEvent * e )
|
|
|
|
{
|
|
|
|
const bool ret = KLineEdit::event( e );
|
|
|
|
KexiDBTextWidgetInterface::event(e, this, text().isEmpty());
|
|
|
|
if (e->type()==TQEvent::FocusOut) {
|
|
|
|
TQFocusEvent *fe = TQT_TQFOCUSEVENT(e);
|
|
|
|
// if (fe->reason()!=TQFocusEvent::ActiveWindow && fe->reason()!=TQFocusEvent::Popup) {
|
|
|
|
if (fe->reason()==TQFocusEvent::Tab || fe->reason()==TQFocusEvent::Backtab) {
|
|
|
|
//display aligned to left after loosing the focus (only if this is tab/backtab event)
|
|
|
|
//! @todo add option to set cursor at the beginning
|
|
|
|
setCursorPosition(0); //ok?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::appendStretchRequired(KexiDBAutoField* autoField) const
|
|
|
|
{
|
|
|
|
return KexiDBAutoField::Top == autoField->labelPosition();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::handleAction(const TQString& actionName)
|
|
|
|
{
|
|
|
|
if (actionName=="edit_copy") {
|
|
|
|
copy();
|
|
|
|
}
|
|
|
|
else if (actionName=="edit_paste") {
|
|
|
|
paste();
|
|
|
|
}
|
|
|
|
else if (actionName=="edit_cut") {
|
|
|
|
cut();
|
|
|
|
}
|
|
|
|
//! @todo ?
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::setDisplayDefaultValue(TQWidget *widget, bool displayDefaultValue)
|
|
|
|
{
|
|
|
|
KexiFormDataItemInterface::setDisplayDefaultValue(widget, displayDefaultValue);
|
|
|
|
// initialize display parameters for default / entered value
|
|
|
|
KexiDisplayUtils::DisplayParameters * const params
|
|
|
|
= displayDefaultValue ? m_displayParametersForDefaultValue : m_displayParametersForEnteredValue;
|
|
|
|
setFont(params->font);
|
|
|
|
TQPalette pal(palette());
|
|
|
|
pal.setColor(TQPalette::Active, TQColorGroup::Text, params->textColor);
|
|
|
|
setPalette(pal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::undo()
|
|
|
|
{
|
|
|
|
cancelEditor();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::moveCursorToEnd()
|
|
|
|
{
|
|
|
|
KLineEdit::end(false/*!mark*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::moveCursorToStart()
|
|
|
|
{
|
|
|
|
KLineEdit::home(false/*!mark*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiDBLineEdit::selectAll()
|
|
|
|
{
|
|
|
|
KLineEdit::selectAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiDBLineEdit::keyPressed(TQKeyEvent *ke)
|
|
|
|
{
|
|
|
|
Q_UNUSED(ke);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kexidblineedit.moc"
|