kexi

kexidbautofield.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2005 Christian Nitschkowski <segfault_ii@web.de>
00004    Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
00005 
00006    This program is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this program; see the file COPYING.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "kexidbautofield.h"
00023 
00024 #include <qlabel.h>
00025 #include <qlayout.h>
00026 #include <qpainter.h>
00027 
00028 #include <kdebug.h>
00029 #include <klocale.h>
00030 
00031 #include "kexidbcheckbox.h"
00032 #include "kexidbdateedit.h"
00033 #include "kexidbdatetimeedit.h"
00034 #include "kexidbdoublespinbox.h"
00035 #include "kexidbimagebox.h"
00036 #include "kexidbintspinbox.h"
00037 #include "kexidblabel.h"
00038 #include "kexidblineedit.h"
00039 #include "kexidbtextedit.h"
00040 #include "kexidbtimeedit.h"
00041 #include "kexipushbutton.h"
00042 #include "kexidbform.h"
00043 
00044 #include <kexidb/queryschema.h>
00045 #include <formeditor/utils.h>
00046 #include <kexiutils/utils.h>
00047 
00048 #define KexiDBAutoField_SPACING 10 //10 pixel for spacing between a label and an editor widget
00049 
00050 KexiDBAutoField::KexiDBAutoField(const QString &text, WidgetType type, LabelPosition pos, 
00051     QWidget *parent, const char *name, bool designMode)
00052  : QWidget(parent, name)
00053  , KexiFormDataItemInterface()
00054  , KFormDesigner::DesignTimeDynamicChildWidgetHandler()
00055  , m_designMode(designMode)
00056 {
00057     init(text, type, pos);
00058 }
00059 
00060 KexiDBAutoField::KexiDBAutoField(QWidget *parent, const char *name, bool designMode)
00061  : QWidget(parent, name)
00062  , KexiFormDataItemInterface()
00063  , KFormDesigner::DesignTimeDynamicChildWidgetHandler()
00064  , m_designMode(designMode)
00065 {
00066     init(QString::null/*i18n("Auto Field")*/, Auto, Left);
00067 }
00068 
00069 KexiDBAutoField::~KexiDBAutoField()
00070 {
00071 }
00072 
00073 void
00074 KexiDBAutoField::init(const QString &text, WidgetType type, LabelPosition pos)
00075 {
00076     m_fieldTypeInternal = KexiDB::Field::InvalidType;
00077     m_layout = 0;
00078     m_editor = 0;
00079     m_label = new QLabel(text, this);
00080     QFontMetrics fm( font() );
00081     //m_label->setFixedWidth( fm.width("This is a test string length") );
00082     m_autoCaption = true;
00083     m_focusPolicyChanged = false;
00084     m_widgetType = Auto;
00085     m_widgetType_property = (type==Auto ? Text : type); //to force "differ" to be true in setWidgetType()
00086     setWidgetType(type);
00087     setLabelPosition(pos);
00088 }
00089 
00090 void
00091 KexiDBAutoField::setWidgetType(WidgetType type)
00092 {
00093     const bool differ = (type != m_widgetType_property);
00094     m_widgetType_property = type;
00095     if(differ) {
00096         if(type == Auto) {// try to guess type from data source type
00097             if (columnInfo())
00098                 m_widgetType = KexiDBAutoField::widgetTypeForFieldType(columnInfo()->field->type());
00099             else
00100                 m_widgetType = Auto;
00101         }
00102         else
00103             m_widgetType = m_widgetType_property;
00104         createEditor();
00105     }
00106 }
00107 
00108 void
00109 KexiDBAutoField::createEditor()
00110 {
00111     if(m_editor)
00112         delete m_editor;
00113 
00114     switch( m_widgetType ) {
00115         case Text:
00116         case Enum: 
00117         case Double: 
00118         case Integer: 
00119             m_editor = new KexiDBLineEdit( this );
00120             connect( m_editor, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotValueChanged() ) );
00121             break;
00122         case MultiLineText:
00123             m_editor = new KexiDBTextEdit( this );
00124             connect( m_editor, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotValueChanged() ) );
00125             break;
00126         case Boolean:
00127             m_editor = new KexiDBCheckBox(m_dataSource, this);
00128             connect( m_editor, SIGNAL(stateChanged()), this, SLOT(slotValueChanged()));
00129             break;
00131         case Date:
00132             m_editor = new KexiDBDateEdit(QDate::currentDate(), this);
00133             connect( m_editor, SIGNAL( dateChanged(const QDate&) ), this, SLOT( slotValueChanged() ) );
00134             break;
00135         case DateTime:
00136             m_editor = new KexiDBDateTimeEdit(QDateTime::currentDateTime(), this);
00137             connect( m_editor, SIGNAL(dateTimeChanged()), this, SLOT( slotValueChanged() ) );
00138             break;
00139         case Time:
00140             m_editor = new KexiDBTimeEdit(QTime::currentTime(), this);
00141             connect( m_editor, SIGNAL( valueChanged( const QTime& ) ), this, SLOT( slotValueChanged() ) );
00142             break;
00143 /*      case Double:
00144             m_editor = new KexiDBDoubleSpinBox(this);
00145             connect( m_editor, SIGNAL( valueChanged(double) ), this, SLOT( slotValueChanged() ) );
00146             break;
00147         case Integer:
00148             m_editor = new KexiDBIntSpinBox(this);
00149             connect( m_editor, SIGNAL(valueChanged(int)), this, SLOT( slotValueChanged() ) );
00150             break;*/
00151         case Image:
00152             m_editor = new KexiDBImageBox(m_designMode, this);
00153             connect( m_editor, SIGNAL(valueChanged()), this, SLOT( slotValueChanged() ) );
00154             break;
00155         default:
00156             m_editor = 0;
00157             changeText(m_caption);
00158             //m_label->setText( m_dataSource.isEmpty() ? "<datasource>" : m_dataSource );
00159             break;
00160     }
00161 
00162     if(m_editor) {
00163         m_editor->setName( QCString("KexiDBAutoField_")+m_editor->className() );
00164         dynamic_cast<KexiDataItemInterface*>(m_editor)->setParentDataItemInterface(this);
00165         KFormDesigner::DesignTimeDynamicChildWidgetHandler::childWidgetAdded(this);
00166         m_editor->show();
00167         m_label->setBuddy(m_editor);
00168         if (m_focusPolicyChanged) {//if focusPolicy is changed at top level, editor inherits it
00169             m_editor->setFocusPolicy(focusPolicy());
00170         }
00171         else {//if focusPolicy is not changed at top level, inherit it from editor
00172             QWidget::setFocusPolicy(m_editor->focusPolicy());
00173         }
00174 //      KFormDesigner::installRecursiveEventFilter(m_editor, this);
00175     }
00176 
00177     setLabelPosition(labelPosition());
00178 }
00179 
00180 void
00181 KexiDBAutoField::setLabelPosition(LabelPosition position)
00182 {
00183     m_lblPosition = position;
00184     if(m_layout) {
00185         delete m_layout;
00186         m_layout = 0;
00187     }
00188 
00189     if(m_editor)
00190         m_editor->show();
00192     if (position==Top || position==Left) {
00193         int align = m_label->alignment();
00194         if(position == Top) {
00195             m_layout = (QBoxLayout*) new QVBoxLayout(this);
00196             align |= AlignVertical_Mask;
00197             align ^= AlignVertical_Mask;
00198             align |= AlignTop;
00199         }
00200         else {
00201             m_layout = (QBoxLayout*) new QHBoxLayout(this);
00202             align |= AlignVertical_Mask;
00203             align ^= AlignVertical_Mask;
00204             align |= AlignVCenter;
00205         }
00206         m_label->setAlignment(align);
00207         if(m_widgetType == Boolean)
00208             m_label->hide();
00209         else
00210             m_label->show();
00211         m_layout->addWidget(m_label);
00212         m_layout->addSpacing(KexiDBAutoField_SPACING);
00213         m_layout->addWidget(m_editor);
00214 //      if(m_editor)
00215     //      m_editor->setSizePolicy(...);
00216     }
00217     else {
00218         m_layout = (QBoxLayout*) new QHBoxLayout(this);
00219         m_label->hide();
00220         m_layout->addWidget(m_editor);
00221     }
00222     //a hack to force layout to be refreshed (any better idea for this?)
00223     resize(size()+QSize(1,0));
00224     resize(size()-QSize(1,0));
00225 }
00226 
00227 void
00228 KexiDBAutoField::setInvalidState( const QString &text )
00229 {
00230     // Widget with an invalid dataSource is just a QLabel
00231     if (m_designMode)
00232         return;
00233     m_widgetType = Auto;
00234     createEditor();
00235     setFocusPolicy(QWidget::NoFocus);
00236     if (m_editor)
00237         m_editor->setFocusPolicy(QWidget::NoFocus);
00239     m_label->setText( text );
00240 }
00241 
00242 bool
00243 KexiDBAutoField::isReadOnly() const
00244 {
00245     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00246     if(iface)
00247         return iface->isReadOnly();
00248     else
00249         return false;
00250 }
00251 /*
00252 void
00253 KexiDBAutoField::setReadOnly(bool state)
00254 {
00255     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00256     if(iface)
00257         iface->setReadOnly(state);
00258 }*/
00259 
00260 void
00261 KexiDBAutoField::setValueInternal(const QVariant& add, bool removeOld)
00262 {
00263     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00264     if(iface)
00265         iface->setValue(m_origValue, add, removeOld);
00266 }
00267 
00268 QVariant
00269 KexiDBAutoField::value()
00270 {
00271     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00272     if(iface)
00273         return iface->value();
00274     return QVariant();
00275 }
00276 
00277 void
00278 KexiDBAutoField::slotValueChanged()
00279 {
00280     signalValueChanged();
00281 }
00282 
00283 bool
00284 KexiDBAutoField::valueIsNull()
00285 {
00286     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00287     if(iface)
00288         return iface->valueIsNull();
00289     return true;
00290 }
00291 
00292 bool
00293 KexiDBAutoField::valueIsEmpty()
00294 {
00295     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00296     if(iface)
00297         return iface->valueIsEmpty();
00298     return true;
00299 }
00300 
00301 bool
00302 KexiDBAutoField::valueChanged()
00303 {
00304     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00305     kexipluginsdbg << m_origValue  << endl;
00306     if(iface)
00307         return iface->valueChanged();
00308     return false;
00309 }
00310 
00311 void
00312 KexiDBAutoField::installListener(KexiDataItemChangesListener* listener)
00313 {
00314     KexiFormDataItemInterface::installListener(listener);
00315     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00316     if(iface)
00317         iface->installListener(listener);
00318 }
00319 
00320 bool
00321 KexiDBAutoField::cursorAtStart()
00322 {
00323     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00324     if(iface)
00325         return iface->cursorAtStart();
00326     return false;
00327 }
00328 
00329 bool
00330 KexiDBAutoField::cursorAtEnd()
00331 {
00332     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00333     if(iface)
00334         return iface->cursorAtEnd();
00335     return false;
00336 }
00337 
00338 void
00339 KexiDBAutoField::clear()
00340 {
00341     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00342     if(iface)
00343         iface->clear();
00344 }
00345 
00346 void
00347 KexiDBAutoField::setFieldTypeInternal(int kexiDBFieldType)
00348 {
00349     m_fieldTypeInternal = (KexiDB::Field::Type)kexiDBFieldType;
00350     WidgetType type = KexiDBAutoField::widgetTypeForFieldType(
00351         m_fieldTypeInternal==KexiDB::Field::InvalidType ? KexiDB::Field::Text : m_fieldTypeInternal);
00352 
00353     if(m_widgetType != type) {
00354         m_widgetType = type;
00355         createEditor();
00356     }
00357     setFieldCaptionInternal(m_fieldCaptionInternal);
00358 }
00359 
00360 void
00361 KexiDBAutoField::setFieldCaptionInternal(const QString& text)
00362 {
00363     m_fieldCaptionInternal = text;
00364     //change text only if autocaption is set and no columnInfo is available
00365     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00366     if((!iface || !iface->columnInfo()) && m_autoCaption) {
00367         changeText(m_fieldCaptionInternal);
00368     }
00369 }
00370 
00371 void
00372 KexiDBAutoField::setColumnInfo(KexiDB::QueryColumnInfo* cinfo)
00373 {
00374     KexiFormDataItemInterface::setColumnInfo(cinfo);
00375 
00376     // change widget type depending on field type
00377     if(m_widgetType_property == Auto) {
00378         WidgetType newWidgetType = Auto;
00379         KexiDB::Field::Type fieldType;
00380         if (cinfo)
00381             fieldType = cinfo->field->type();
00382         else if (dataSource().isEmpty())
00383             fieldType = KexiDB::Field::InvalidType;
00384         else
00385             fieldType = KexiDB::Field::Text;
00386 
00387         if (fieldType != KexiDB::Field::InvalidType) {
00388             newWidgetType = KexiDBAutoField::widgetTypeForFieldType( fieldType );
00389         }
00390         if(m_widgetType != newWidgetType || newWidgetType==Auto) {
00391             m_widgetType = newWidgetType;
00392             createEditor();
00393         }
00394     }
00395     // update label's text
00396     changeText((cinfo && m_autoCaption) ? cinfo->captionOrAliasOrName() : QString::null);
00397 
00398     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00399     if(iface)
00400         iface->setColumnInfo(cinfo);
00401 }
00402 
00403 //static
00404 KexiDBAutoField::WidgetType
00405 KexiDBAutoField::widgetTypeForFieldType(KexiDB::Field::Type type)
00406 {
00407     switch(type) {
00408         case KexiDB::Field::Integer:
00409         case KexiDB::Field::ShortInteger:
00410         case KexiDB::Field::BigInteger:
00411             return Integer;
00412         case  KexiDB::Field::Boolean:
00413             return Boolean;
00414         case KexiDB::Field::Float:
00415         case KexiDB::Field::Double:
00416             return Double;
00417         case KexiDB::Field::Date:
00418             return Date;
00419         case KexiDB::Field::DateTime:
00420             return DateTime;
00421         case KexiDB::Field::Time:
00422             return Time;
00423         case KexiDB::Field::Text:
00424             return Text;
00425         case KexiDB::Field::LongText:
00426             return MultiLineText;
00427         case KexiDB::Field::Enum:
00428             return Enum;
00429         case KexiDB::Field::InvalidType:
00430             return Auto;
00431         case KexiDB::Field::BLOB:
00432         default:
00433             break;
00434     }
00435     return Text;
00436 }
00437 
00438 void
00439 KexiDBAutoField::changeText(const QString &text, bool beautify)
00440 {
00441     QString realText;
00442     bool unbound = false;
00443     if (m_autoCaption && (m_widgetType==Auto || dataSource().isEmpty())) {
00444         realText = QString::fromLatin1(name())+" "+i18n("Unbound Auto Field", " (unbound)");
00445         unbound = true;
00446     }
00447     else {
00448         if (beautify) {
00452             if (!text.isEmpty()) {
00453                 realText = text[0].upper() + text.mid(1);
00454                 if (m_widgetType!=Boolean) {
00456                     realText += ": ";
00457                 }
00458             }
00459         }
00460         else
00461             realText = text;
00462     }
00463 
00464     QWidget* widgetToAlterForegroundColor;
00465     if(m_widgetType == Boolean) {
00466         static_cast<QCheckBox*>(m_editor)->setText(realText);
00467         widgetToAlterForegroundColor = m_editor;
00468     }
00469     else {
00470         m_label->setText(realText);
00471         widgetToAlterForegroundColor = m_label;
00472     }
00473 
00474 /*  if (unbound)
00475         widgetToAlterForegroundColor->setPaletteForegroundColor( 
00476             KexiUtils::blendedColors(
00477                 widgetToAlterForegroundColor->paletteForegroundColor(), 
00478                 widgetToAlterForegroundColor->paletteBackgroundColor(), 2, 1));
00479     else
00480         widgetToAlterForegroundColor->setPaletteForegroundColor( paletteForegroundColor() );*/
00481 }
00482 
00483 void
00484 KexiDBAutoField::setCaption(const QString &caption)
00485 {
00486     m_caption = caption;
00487     if(!m_autoCaption && !caption.isEmpty())
00488         changeText(m_caption);
00489 }
00490 
00491 /*void
00492 KexiDBAutoField::setCaptionInternal(const QString& text)
00493 {
00494     if(!m_autoCaption && !caption.isEmpty())
00495 }*/
00496 
00497 void
00498 KexiDBAutoField::setAutoCaption(bool autoCaption)
00499 {
00500     m_autoCaption = autoCaption;
00501     if(m_autoCaption) {
00502         //m_caption = QString::null;
00503         if(columnInfo()) {
00504             changeText(columnInfo()->captionOrAliasOrName());
00505         }
00506         else {
00507             changeText(m_fieldCaptionInternal);
00508         }
00509     }
00510     else
00511         changeText(m_caption);
00512 
00513 //  if(!m_autoCaption && !m_caption.isEmpty())
00514 //      changeText(m_caption);
00515 }
00516 
00517 void
00518 KexiDBAutoField::setDataSource( const QString &ds ) {
00519     KexiFormDataItemInterface::setDataSource(ds);
00520     if (ds.isEmpty()) {
00521         setColumnInfo(0);
00522     }
00523 }
00524 
00525 QSize
00526 KexiDBAutoField::sizeHint() const
00527 {
00528     if (m_lblPosition == NoLabel)
00529         return m_editor ? m_editor->sizeHint() : QWidget::sizeHint();
00530 
00531     QSize s1(0,0);
00532     if (m_editor)
00533         s1 = m_editor->sizeHint();
00534     QSize s2(m_label->sizeHint());
00535     if (m_lblPosition == Top)
00536         return QSize(QMAX(s1.width(), s2.width()), s1.height()+KexiDBAutoField_SPACING+s2.height());
00537 
00538 //  if (m_lblPosition == Left) 
00539     //left
00540     return QSize(s1.width()+KexiDBAutoField_SPACING+s2.width(), QMAX(s1.height(), s2.height()));
00541 }
00542 
00543 void
00544 KexiDBAutoField::setFocusPolicy( FocusPolicy policy )
00545 {
00546     m_focusPolicyChanged = true;
00547     QWidget::setFocusPolicy(policy);
00548     m_label->setFocusPolicy(policy);
00549     if (m_editor)
00550         m_editor->setFocusPolicy(policy);
00551 }
00552 
00553 void
00554 KexiDBAutoField::updateInformationAboutUnboundField()
00555 {
00556     if (   (m_autoCaption && (dataSource().isEmpty() || dataSourceMimeType().isEmpty()))
00557         || (!m_autoCaption && m_caption.isEmpty()) )
00558     {
00559         m_label->setText( QString::fromLatin1(name())+" "+i18n("Unbound Auto Field", " (unbound)") );
00560     }
00561 //  else
00562 //      m_label->setText( QString::fromLatin1(name())+" "+i18n(" (unbound)") );
00563 }
00564 
00565 /*void
00566 KexiDBAutoField::paintEvent( QPaintEvent* pe )
00567 {
00568     QWidget::paintEvent( pe );
00569 
00570     if (   (m_autoCaption && (dataSource().isEmpty() || dataSourceMimeType().isEmpty()))
00571         || (!m_autoCaption && m_caption.isEmpty()) )
00572     {
00573         QPainter p(this);
00574         p.setPen( m_label->paletteForegroundColor() );
00575         p.setClipRect(pe->rect());
00576         p.setFont(m_label->font());
00577         p.drawText(rect(), Qt::AlignLeft | Qt::WordBreak, 
00578             QString::fromLatin1(name())+" "+i18n(" (unbound)"));
00579     }
00580 }*/
00581 
00582 void
00583 KexiDBAutoField::paletteChange( const QPalette& oldPal )
00584 {
00585     Q_UNUSED(oldPal);
00586     m_label->setPalette( palette() );
00587 }
00588 
00589 
00590 #include "kexidbautofield.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys