kexi

kexiinputtableedit.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
00003    Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this program; see the file COPYING.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "kexiinputtableedit.h"
00022 
00023 #include <qregexp.h>
00024 #include <qevent.h>
00025 #include <qlayout.h>
00026 #include <qtimer.h>
00027 #include <qpainter.h>
00028 #include <qapplication.h>
00029 #include <qclipboard.h>
00030 #include <qtooltip.h>
00031 
00032 #include <kglobal.h>
00033 #include <klocale.h>
00034 #include <kdebug.h>
00035 #include <kglobalsettings.h>
00036 #include <kcompletionbox.h>
00037 #include <knumvalidator.h>
00038 #include <kexiutils/longlongvalidator.h>
00039 #include <kexidb/field.h>
00040 #include <kexidb/fieldvalidator.h>
00041 
00043 class MyLineEdit : public KLineEdit
00044 {
00045     public:
00046         MyLineEdit(QWidget *parent, const char *name) : KLineEdit(parent,name)
00047         {}
00048     protected:
00049         virtual void drawFrame ( QPainter * p ) {
00050             p->setPen( QPen( colorGroup().text() ) );
00051             QRect r = rect();
00052             p->moveTo( r.topLeft() );
00053             p->lineTo( r.topRight() );
00054             p->lineTo( r.bottomRight() );
00055             p->lineTo( r.bottomLeft() );
00056             if (pos().x() == 0) //draw left side only when it is @ the edge
00057                 p->lineTo( r.topLeft() );
00058         }
00059 };
00060 
00061 //======================================================
00062 
00063 KexiInputTableEdit::KexiInputTableEdit(KexiTableViewColumn &column, QWidget *parent)
00064  : KexiTableEdit(column, parent)
00065 {
00066     setName("KexiInputTableEdit");
00067 //  m_type = f.type(); //copied because the rest of code uses m_type
00068 //  m_field = &f;
00069 //  m_origValue = value;//original value
00070     init();
00071 }
00072 
00073 KexiInputTableEdit::~KexiInputTableEdit()
00074 {
00075 }
00076 
00077 void KexiInputTableEdit::init()
00078 {
00079 //  kdDebug() << "KexiInputTableEdit: m_origValue.typeName()==" << m_origValue.typeName() << endl;
00080 //  kdDebug() << "KexiInputTableEdit: type== " << field()->typeName() << endl;
00081 //  kdDebug() << "KexiInputTableEdit: displayed type== " << displayedField()->typeName() << endl;
00082 
00083     m_textFormatter.setField( field() );
00084 
00085     //init settings
00086     m_decsym = KGlobal::locale()->decimalSymbol();
00087     if (m_decsym.isEmpty())
00088         m_decsym=".";//default
00089 
00090     const bool align_right = displayedField()->isNumericType();
00091 
00092     if (!align_right) {
00093         //create layer for internal editor
00094         QHBoxLayout *lyr = new QHBoxLayout(this);
00095         lyr->addSpacing(4);
00096         lyr->setAutoAdd(true);
00097     }
00098 
00099     //create internal editor
00100     m_lineedit = new MyLineEdit(this, "KexiInputTableEdit-KLineEdit");
00101     setViewWidget(m_lineedit);
00102     if (align_right)
00103         m_lineedit->setAlignment(AlignRight);
00104 //  m_cview->setFrame(false);
00105 //  m_cview->setFrameStyle( QFrame::Plain | QFrame::Box );
00106 //  m_cview->setLineWidth( 1 );
00107     m_calculatedCell = false;
00108 
00109 #if 0 //js TODO
00110     connect(m_cview->completionBox(), SIGNAL(activated(const QString &)),
00111      this, SLOT(completed(const QString &)));
00112     connect(m_cview->completionBox(), SIGNAL(highlighted(const QString &)),
00113      this, SLOT(completed(const QString &)));
00114      m_cview->completionBox()->setTabHandling(true);
00115 #endif
00116 
00117 }
00118 
00119 void KexiInputTableEdit::setValueInternal(const QVariant& add, bool removeOld)
00120 {
00121     QString text( m_textFormatter.valueToText(removeOld ? QVariant() : m_origValue, add.toString()) );
00122     if (text.isEmpty()) {
00123         if (m_origValue.toString().isEmpty()) {
00124             //we have to set NULL initial value:
00125             m_lineedit->setText(QString::null);
00126         }
00127     }
00128     else {
00129         m_lineedit->setText(text);
00130     }
00131 
00132 #if 0
00133 //move to end is better by default
00134         m_cview->selectAll();
00135 #else
00136 //js TODO: by default we're moving to the end of editor, ADD OPTION allowing "select all chars"
00137         m_lineedit->end(false);
00138 #endif
00139 
00140     if (!m_lineedit->validator()) {
00141         QValidator *validator = new KexiDB::FieldValidator(
00142             *field(), m_lineedit, "KexiInputTableEdit-validator");
00143         m_lineedit->setValidator( validator );
00144     }
00145 }
00146 
00147 #if 0
00148 //moved to KexiTextFormatter
00149 QString KexiInputTableEdit::valueToText(KexiDB::Field* field, const QVariant& value, const QString& add)
00150 {
00151     QString text; //result
00152 
00153     if (field->isFPNumericType()) {
00156         text = QString::number(value.toDouble(), 'f', 
00157             QMAX(field->visibleDecimalPlaces(), 10)); //<-- 10 is quite good maximum for fractional digits 
00159         if (value.toDouble() == 0.0) {
00160             text = add.isEmpty() ? "0" : add; //eat 0
00161         }
00162         else {
00164             QStringList sl = QStringList::split(".", text);
00165             if (text.isEmpty()) {
00166                 //nothing
00167             }
00168             else if (sl.count()==2) {
00169 //              kdDebug() << "sl.count()=="<<sl.count()<< " " <<sl[0] << " | " << sl[1] << endl;
00170                 const QString sl1 = sl[1];
00171                 int pos = sl1.length()-1;
00172                 if (pos>=1) {
00173                     for (;pos>=0 && sl1[pos]=='0';pos--)
00174                         ;
00175                     pos++;
00176                 }
00177                 if (pos>0)
00178                     text = sl[0] + m_decsym + sl1.left(pos);
00179                 else
00180                     text = sl[0]; //no decimal point
00181             }
00182             text += add;
00183         }
00184 /*moved to KexiDB::FieldValidator
00185         if (setValidator && !m_lineedit->validator()) {
00186             QValidator *validator = new KDoubleValidator(m_lineedit);
00187             m_lineedit->setValidator( validator );
00188         }*/
00189     }
00190     else {
00191         text = value.toString();
00192         if (field->isIntegerType()) {
00193             if (value.toInt() == 0) {
00194                 text = add; //eat 0
00195             }
00196             else {
00197                 text += add;
00198             }
00199 /*moved to KexiDB::FieldValidator
00201             if (setValidator && !m_lineedit->validator()) {
00202                 QValidator *validator;
00203                 if (KexiDB::Field::BigInteger == field()->type()) {
00205                     validator = new KexiUtils::LongLongValidator(m_lineedit); 
00206                 }
00207                 else {
00208                     validator = new KIntValidator(m_lineedit);
00209                 }
00210                 m_lineedit->setValidator( validator );
00211             }*/
00212         }
00213         else {//default: text
00214             text += add;
00215         }
00216     }
00217 
00218     return text;
00219 }
00220 #endif
00221 
00222 void KexiInputTableEdit::paintEvent ( QPaintEvent * /*e*/ )
00223 {
00224     QPainter p(this);
00225     p.setPen( QPen( colorGroup().text() ) );
00226     p.drawRect( rect() );
00227 }
00228 
00229 void
00230 KexiInputTableEdit::setRestrictedCompletion()
00231 {
00232 #if 0 //js TODO
00233 kdDebug() << "KexiInputTableEdit::setRestrictedCompletion()" << endl;
00234 //  KLineEdit *content = static_cast<KLineEdit*>(m_view);
00235     if(m_cview->text().isEmpty())
00236         return;
00237 
00238     kdDebug() << "KexiInputTableEdit::setRestrictedCompletion(): something to do" << endl;
00239 
00240     m_cview->useGlobalKeyBindings();
00241 
00242     QStringList newC;
00243     QStringList::ConstIterator it, end( m_comp.constEnd() );
00244     for( it = m_comp.constBegin(); it != end; ++it)
00245     {
00246         if((*it).startsWith(m_cview->text()))
00247             newC.append(*it);
00248     }
00249     m_cview->setCompletedItems(newC);
00250 #endif
00251 }
00252 
00253 void
00254 KexiInputTableEdit::completed(const QString &s)
00255 {
00256 //  kdDebug() << "KexiInputTableEdit::completed(): " << s << endl;
00257     m_lineedit->setText(s);
00258 }
00259 
00260 bool KexiInputTableEdit::valueChanged()
00261 {
00262     //not needed? if (m_lineedit->text()!=m_origValue.toString())
00263     //not needed?   return true;
00264     return KexiTableEdit::valueChanged();
00265 }
00266 
00267 bool KexiInputTableEdit::valueIsNull()
00268 {
00269     return m_lineedit->text().isNull();
00270 }
00271 
00272 bool KexiInputTableEdit::valueIsEmpty()
00273 {
00274     return !m_lineedit->text().isNull() && m_lineedit->text().isEmpty();
00275 }
00276 
00277 QVariant KexiInputTableEdit::value()
00278 {
00279     if (field()->isFPNumericType()) {//==KexiDB::Field::Double || m_type==KexiDB::Field::Float) {
00281         QString txt = m_lineedit->text();
00282         if (m_decsym!=".")
00283             txt = txt.replace(m_decsym,".");//convert back
00284         bool ok;
00285         const double result = txt.toDouble(&ok);
00286         return ok ? QVariant(result) : QVariant();
00287     }
00288     else if (field()->isIntegerType()) {
00290         bool ok;
00291         if (KexiDB::Field::BigInteger == field()->type()) {
00292             if (field()->isUnsigned()) {
00293                 const Q_ULLONG result = m_lineedit->text().toULongLong(&ok);
00294                 return ok ? QVariant(result) : QVariant();
00295             }
00296             else {
00297                 const Q_LLONG result = m_lineedit->text().toLongLong(&ok);
00298                 return ok ? QVariant(result) : QVariant();
00299             }
00300         }
00301         if (KexiDB::Field::Integer == field()->type()) {
00302             if (field()->isUnsigned()) {
00303                 const uint result = m_lineedit->text().toUInt(&ok);
00304                 return ok ? QVariant(result) : QVariant();
00305             }
00306         }
00307         //default: signed int
00308         const int result = m_lineedit->text().toInt(&ok);
00309         return ok ? QVariant(result) : QVariant();
00310     }
00311     //default: text
00312     return m_lineedit->text();
00313 }
00314 
00315 void
00316 KexiInputTableEdit::clear()
00317 {
00318     m_lineedit->clear();
00319 }
00320 
00321 bool KexiInputTableEdit::cursorAtStart()
00322 {
00323     return m_lineedit->cursorPosition()==0;
00324 }
00325 
00326 bool KexiInputTableEdit::cursorAtEnd()
00327 {
00328     return m_lineedit->cursorPosition()==(int)m_lineedit->text().length();
00329 }
00330 
00331 QSize KexiInputTableEdit::totalSize()
00332 {
00333     if (!m_lineedit)
00334         return size();
00335     return m_lineedit->size();
00336 }
00337 
00338 void KexiInputTableEdit::handleCopyAction(const QVariant& value, const QVariant& visibleValue)
00339 {
00340     Q_UNUSED(visibleValue);
00342     qApp->clipboard()->setText( m_textFormatter.valueToText(value, QString::null) );
00343 }
00344 
00345 void KexiInputTableEdit::handleAction(const QString& actionName)
00346 {
00347     const bool alreadyVisible = m_lineedit->isVisible();
00348 
00349     if (actionName=="edit_paste") {
00350         if (!alreadyVisible) { //paste as the entire text if the cell was not in edit mode
00351             emit editRequested();
00352             m_lineedit->clear();
00353         }
00354         m_lineedit->paste();
00355     }
00356     else if (actionName=="edit_cut") {
00358         if (!alreadyVisible) { //cut the entire text if the cell was not in edit mode
00359             emit editRequested();
00360             m_lineedit->selectAll();
00361         }
00362         m_lineedit->cut();
00363     }
00364 }
00365 
00366 bool KexiInputTableEdit::showToolTipIfNeeded(const QVariant& value, const QRect& rect, 
00367     const QFontMetrics& fm, bool focused)
00368 {
00369     QString text( value.type()==QVariant::String ? value.toString()
00370         : m_textFormatter.valueToText(value, QString::null) );
00371     QRect internalRect(rect);
00372     internalRect.setLeft(rect.x()+leftMargin());
00373     internalRect.setWidth(internalRect.width()-rightMargin(focused)-2*3);
00374     kexidbg << rect << " " << internalRect << " " << fm.width(text) << endl;
00375     return fm.width(text) > internalRect.width();
00376 }
00377 
00378 void KexiInputTableEdit::moveCursorToEnd()
00379 {
00380     m_lineedit->end(false);
00381 }
00382 
00383 void KexiInputTableEdit::moveCursorToStart()
00384 {
00385     m_lineedit->home(false);
00386 }
00387 
00388 void KexiInputTableEdit::selectAll()
00389 {
00390     m_lineedit->selectAll();
00391 }
00392 
00393 KEXI_CELLEDITOR_FACTORY_ITEM_IMPL(KexiInputEditorFactoryItem, KexiInputTableEdit)
00394 
00395 #include "kexiinputtableedit.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys