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: case Enum: 
00116             m_editor = new KexiDBLineEdit( this );
00117             connect( m_editor, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotValueChanged() ) );
00118             break;
00119         case MultiLineText:
00120             m_editor = new KexiDBTextEdit( this );
00121             connect( m_editor, SIGNAL( textChanged( const QString& ) ), this, SLOT( slotValueChanged() ) );
00122             break;
00123         case Boolean:
00124             m_editor = new KexiDBCheckBox(m_dataSource, this);
00125             connect( m_editor, SIGNAL(stateChanged()), this, SLOT(slotValueChanged()));
00126             break;
00128         case Date:
00129             m_editor = new KexiDBDateEdit(QDate::currentDate(), this);
00130             connect( m_editor, SIGNAL( dateChanged(const QDate&) ), this, SLOT( slotValueChanged() ) );
00131             break;
00132         case DateTime:
00133             m_editor = new KexiDBDateTimeEdit(QDateTime::currentDateTime(), this);
00134             connect( m_editor, SIGNAL(dateTimeChanged()), this, SLOT( slotValueChanged() ) );
00135             break;
00136         case Time:
00137             m_editor = new KexiDBTimeEdit(QTime::currentTime(), this);
00138             connect( m_editor, SIGNAL( valueChanged( const QTime& ) ), this, SLOT( slotValueChanged() ) );
00139             break;
00140         case Double:
00141             m_editor = new KexiDBDoubleSpinBox(this);
00142             connect( m_editor, SIGNAL( valueChanged(double) ), this, SLOT( slotValueChanged() ) );
00143             break;
00144         case Integer:
00145             m_editor = new KexiDBIntSpinBox(this);
00146             connect( m_editor, SIGNAL(valueChanged(int)), this, SLOT( slotValueChanged() ) );
00147             break;
00148         case Image:
00149             m_editor = new KexiDBImageBox(m_designMode, this);
00150             connect( m_editor, SIGNAL(valueChanged()), this, SLOT( slotValueChanged() ) );
00151             break;
00152         default:
00153             m_editor = 0;
00154             changeText(m_caption);
00155             //m_label->setText( m_dataSource.isEmpty() ? "<datasource>" : m_dataSource );
00156             break;
00157     }
00158 
00159     if(m_editor) {
00160         m_editor->setName( QCString("KexiDBAutoField_")+m_editor->className() );
00161         dynamic_cast<KexiDataItemInterface*>(m_editor)->setParentDataItemInterface(this);
00162         KFormDesigner::DesignTimeDynamicChildWidgetHandler::childWidgetAdded(this);
00163         m_editor->show();
00164         m_label->setBuddy(m_editor);
00165         if (m_focusPolicyChanged) {//if focusPolicy is changed at top level, editor inherits it
00166             m_editor->setFocusPolicy(focusPolicy());
00167         }
00168         else {//if focusPolicy is not changed at top level, inherit it from editor
00169             QWidget::setFocusPolicy(m_editor->focusPolicy());
00170         }
00171 //      KFormDesigner::installRecursiveEventFilter(m_editor, this);
00172     }
00173 
00174     setLabelPosition(labelPosition());
00175 }
00176 
00177 void
00178 KexiDBAutoField::setLabelPosition(LabelPosition position)
00179 {
00180     m_lblPosition = position;
00181     if(m_layout) {
00182         delete m_layout;
00183         m_layout = 0;
00184     }
00185 
00186     if(m_editor)
00187         m_editor->show();
00189     if (position==Top || position==Left) {
00190         int align = m_label->alignment();
00191         if(position == Top) {
00192             m_layout = (QBoxLayout*) new QVBoxLayout(this);
00193             align |= AlignVertical_Mask;
00194             align ^= AlignVertical_Mask;
00195             align |= AlignTop;
00196         }
00197         else {
00198             m_layout = (QBoxLayout*) new QHBoxLayout(this);
00199             align |= AlignVertical_Mask;
00200             align ^= AlignVertical_Mask;
00201             align |= AlignVCenter;
00202         }
00203         m_label->setAlignment(align);
00204         if(m_widgetType == Boolean)
00205             m_label->hide();
00206         else
00207             m_label->show();
00208         m_layout->addWidget(m_label);
00209         m_layout->addSpacing(KexiDBAutoField_SPACING);
00210         m_layout->addWidget(m_editor);
00211 //      if(m_editor)
00212     //      m_editor->setSizePolicy(...);
00213     }
00214     else {
00215         m_layout = (QBoxLayout*) new QHBoxLayout(this);
00216         m_label->hide();
00217         m_layout->addWidget(m_editor);
00218     }
00219     //a hack to force layout to be refreshed (any better idea for this?)
00220     resize(size()+QSize(1,0));
00221     resize(size()-QSize(1,0));
00222 }
00223 
00224 void
00225 KexiDBAutoField::setInvalidState( const QString &text )
00226 {
00227     // Widget with an invalid dataSource is just a QLabel
00228     if (m_designMode)
00229         return;
00230     m_widgetType = Auto;
00231     createEditor();
00232     setFocusPolicy(QWidget::NoFocus);
00233     m_editor->setFocusPolicy(QWidget::NoFocus);
00235     m_label->setText( text );
00236 }
00237 
00238 bool
00239 KexiDBAutoField::isReadOnly() const
00240 {
00241     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00242     if(iface)
00243         return iface->isReadOnly();
00244     else
00245         return false;
00246 }
00247 /*
00248 void
00249 KexiDBAutoField::setReadOnly(bool state)
00250 {
00251     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00252     if(iface)
00253         iface->setReadOnly(state);
00254 }*/
00255 
00256 void
00257 KexiDBAutoField::setValueInternal(const QVariant& add, bool removeOld)
00258 {
00259     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00260     if(iface)
00261         iface->setValue(m_origValue, add, removeOld);
00262 }
00263 
00264 QVariant
00265 KexiDBAutoField::value()
00266 {
00267     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00268     if(iface)
00269         return iface->value();
00270     return QVariant();
00271 }
00272 
00273 void
00274 KexiDBAutoField::slotValueChanged()
00275 {
00276     signalValueChanged();
00277 }
00278 
00279 bool
00280 KexiDBAutoField::valueIsNull()
00281 {
00282     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00283     if(iface)
00284         return iface->valueIsNull();
00285     return true;
00286 }
00287 
00288 bool
00289 KexiDBAutoField::valueIsEmpty()
00290 {
00291     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00292     if(iface)
00293         return iface->valueIsEmpty();
00294     return true;
00295 }
00296 
00297 bool
00298 KexiDBAutoField::valueChanged()
00299 {
00300     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00301     kexipluginsdbg << m_origValue  << endl;
00302     if(iface)
00303         return iface->valueChanged();
00304     return false;
00305 }
00306 
00307 void
00308 KexiDBAutoField::installListener(KexiDataItemChangesListener* listener)
00309 {
00310     KexiFormDataItemInterface::installListener(listener);
00311     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00312     if(iface)
00313         iface->installListener(listener);
00314 }
00315 
00316 bool
00317 KexiDBAutoField::cursorAtStart()
00318 {
00319     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00320     if(iface)
00321         return iface->cursorAtStart();
00322     return false;
00323 }
00324 
00325 bool
00326 KexiDBAutoField::cursorAtEnd()
00327 {
00328     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00329     if(iface)
00330         return iface->cursorAtEnd();
00331     return false;
00332 }
00333 
00334 void
00335 KexiDBAutoField::clear()
00336 {
00337     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00338     if(iface)
00339         iface->clear();
00340 }
00341 
00342 void
00343 KexiDBAutoField::setFieldTypeInternal(int kexiDBFieldType)
00344 {
00345     m_fieldTypeInternal = (KexiDB::Field::Type)kexiDBFieldType;
00346     WidgetType type = KexiDBAutoField::widgetTypeForFieldType(
00347         m_fieldTypeInternal==KexiDB::Field::InvalidType ? KexiDB::Field::Text : m_fieldTypeInternal);
00348 
00349     if(m_widgetType != type) {
00350         m_widgetType = type;
00351         createEditor();
00352     }
00353     setFieldCaptionInternal(m_fieldCaptionInternal);
00354 }
00355 
00356 void
00357 KexiDBAutoField::setFieldCaptionInternal(const QString& text)
00358 {
00359     m_fieldCaptionInternal = text;
00360     //change text only if autocaption is set and no columnInfo is available
00361     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00362     if((!iface || !iface->columnInfo()) && m_autoCaption) {
00363         changeText(m_fieldCaptionInternal);
00364     }
00365 }
00366 
00367 void
00368 KexiDBAutoField::setColumnInfo(KexiDB::QueryColumnInfo* cinfo)
00369 {
00370     KexiFormDataItemInterface::setColumnInfo(cinfo);
00371 
00372     // change widget type depending on field type
00373     if(m_widgetType_property == Auto) {
00374         WidgetType newWidgetType = Auto;
00375         KexiDB::Field::Type fieldType;
00376         if (cinfo)
00377             fieldType = cinfo->field->type();
00378         else if (dataSource().isEmpty())
00379             fieldType = KexiDB::Field::InvalidType;
00380         else
00381             fieldType = KexiDB::Field::Text;
00382 
00383         if (fieldType != KexiDB::Field::InvalidType) {
00384             newWidgetType = KexiDBAutoField::widgetTypeForFieldType( fieldType );
00385         }
00386         if(m_widgetType != newWidgetType || newWidgetType==Auto) {
00387             m_widgetType = newWidgetType;
00388             createEditor();
00389         }
00390     }
00391     // update label's text
00392     changeText((cinfo && m_autoCaption) ? cinfo->captionOrAliasOrName() : QString::null);
00393 
00394     KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
00395     if(iface)
00396         iface->setColumnInfo(cinfo);
00397 }
00398 
00399 //static
00400 KexiDBAutoField::WidgetType
00401 KexiDBAutoField::widgetTypeForFieldType(KexiDB::Field::Type type)
00402 {
00403     switch(type) {
00404         case KexiDB::Field::Integer:
00405         case KexiDB::Field::ShortInteger:
00406         case KexiDB::Field::BigInteger:
00407             return Integer;
00408         case  KexiDB::Field::Boolean:
00409             return Boolean;
00410         case KexiDB::Field::Float:
00411         case KexiDB::Field::Double:
00412             return Double;
00413         case KexiDB::Field::Date:
00414             return Date;
00415         case KexiDB::Field::DateTime:
00416             return DateTime;
00417         case KexiDB::Field::Time:
00418             return Time;
00419         case KexiDB::Field::Text:
00420             return Text;
00421         case KexiDB::Field::LongText:
00422             return MultiLineText;
00423         case KexiDB::Field::Enum:
00424             return Enum;
00425         case KexiDB::Field::InvalidType:
00426             return Auto;
00427         case KexiDB::Field::BLOB:
00428         default:
00429             break;
00430     }
00431     return Text;
00432 }
00433 
00434 void
00435 KexiDBAutoField::changeText(const QString &text, bool beautify)
00436 {
00437     QString realText;
00438     bool unbound = false;
00439     if (m_autoCaption && (m_widgetType==Auto || dataSource().isEmpty())) {
00440         realText = QString::fromLatin1(name())+" "+i18n("Unbound Auto Field", " (unbound)");
00441         unbound = true;
00442     }
00443     else {
00444         if (beautify) {
00448             if (!text.isEmpty()) {
00449                 realText = text[0].upper();
00450                 realText += (text.mid(1) + ": ");
00451             }
00452         }
00453         else
00454             realText = text;
00455     }
00456 
00457     QWidget* widgetToAlterForegroundColor;
00458     if(m_widgetType == Boolean) {
00459         static_cast<QCheckBox*>(m_editor)->setText(realText);
00460         widgetToAlterForegroundColor = m_editor;
00461     }
00462     else {
00463         m_label->setText(realText);
00464         widgetToAlterForegroundColor = m_label;
00465     }
00466 
00467 /*  if (unbound)
00468         widgetToAlterForegroundColor->setPaletteForegroundColor( 
00469             KexiUtils::blendedColors(
00470                 widgetToAlterForegroundColor->paletteForegroundColor(), 
00471                 widgetToAlterForegroundColor->paletteBackgroundColor(), 2, 1));
00472     else
00473         widgetToAlterForegroundColor->setPaletteForegroundColor( paletteForegroundColor() );*/
00474 }
00475 
00476 void
00477 KexiDBAutoField::setCaption(const QString &caption)
00478 {
00479     m_caption = caption;
00480     if(!m_autoCaption && !caption.isEmpty())
00481         changeText(m_caption);
00482 }
00483 
00484 /*void
00485 KexiDBAutoField::setCaptionInternal(const QString& text)
00486 {
00487     if(!m_autoCaption && !caption.isEmpty())
00488 }*/
00489 
00490 void
00491 KexiDBAutoField::setAutoCaption(bool autoCaption)
00492 {
00493     m_autoCaption = autoCaption;
00494     if(m_autoCaption) {
00495         //m_caption = QString::null;
00496         if(columnInfo()) {
00497             changeText(columnInfo()->captionOrAliasOrName());
00498         }
00499         else {
00500             changeText(m_fieldCaptionInternal);
00501         }
00502     }
00503     else
00504         changeText(m_caption);
00505 
00506 //  if(!m_autoCaption && !m_caption.isEmpty())
00507 //      changeText(m_caption);
00508 }
00509 
00510 void
00511 KexiDBAutoField::setDataSource( const QString &ds ) {
00512     KexiFormDataItemInterface::setDataSource(ds);
00513     if (ds.isEmpty()) {
00514         setColumnInfo(0);
00515     }
00516 }
00517 
00518 QSize
00519 KexiDBAutoField::sizeHint() const
00520 {
00521     if (m_lblPosition == NoLabel)
00522         return m_editor ? m_editor->sizeHint() : QWidget::sizeHint();
00523 
00524     QSize s1(0,0);
00525     if (m_editor)
00526         s1 = m_editor->sizeHint();
00527     QSize s2(m_label->sizeHint());
00528     if (m_lblPosition == Top)
00529         return QSize(QMAX(s1.width(), s2.width()), s1.height()+KexiDBAutoField_SPACING+s2.height());
00530 
00531 //  if (m_lblPosition == Left) 
00532     //left
00533     return QSize(s1.width()+KexiDBAutoField_SPACING+s2.width(), QMAX(s1.height(), s2.height()));
00534 }
00535 
00536 void
00537 KexiDBAutoField::setFocusPolicy( FocusPolicy policy )
00538 {
00539     m_focusPolicyChanged = true;
00540     QWidget::setFocusPolicy(policy);
00541     m_label->setFocusPolicy(policy);
00542     if (m_editor)
00543         m_editor->setFocusPolicy(policy);
00544 }
00545 
00546 void
00547 KexiDBAutoField::updateInformationAboutUnboundField()
00548 {
00549     if (   (m_autoCaption && (dataSource().isEmpty() || dataSourceMimeType().isEmpty()))
00550         || (!m_autoCaption && m_caption.isEmpty()) )
00551     {
00552         m_label->setText( QString::fromLatin1(name())+" "+i18n("Unbound Auto Field", " (unbound)") );
00553     }
00554 //  else
00555 //      m_label->setText( QString::fromLatin1(name())+" "+i18n(" (unbound)") );
00556 }
00557 
00558 /*void
00559 KexiDBAutoField::paintEvent( QPaintEvent* pe )
00560 {
00561     QWidget::paintEvent( pe );
00562 
00563     if (   (m_autoCaption && (dataSource().isEmpty() || dataSourceMimeType().isEmpty()))
00564         || (!m_autoCaption && m_caption.isEmpty()) )
00565     {
00566         QPainter p(this);
00567         p.setPen( m_label->paletteForegroundColor() );
00568         p.setClipRect(pe->rect());
00569         p.setFont(m_label->font());
00570         p.drawText(rect(), Qt::AlignLeft | Qt::WordBreak, 
00571             QString::fromLatin1(name())+" "+i18n(" (unbound)"));
00572     }
00573 }*/
00574 
00575 void
00576 KexiDBAutoField::paletteChange( const QPalette& oldPal )
00577 {
00578     Q_UNUSED(oldPal);
00579     m_label->setPalette( palette() );
00580 }
00581 
00582 
00583 #include "kexidbautofield.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys