kexiinputtableedit.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "kexiinputtableedit.h"
22
23#include <tqregexp.h>
24#include <tqevent.h>
25#include <tqlayout.h>
26#include <tqtimer.h>
27#include <tqpainter.h>
28#include <tqapplication.h>
29#include <tqclipboard.h>
30#include <tqtooltip.h>
31
32#include <tdeglobal.h>
33#include <tdelocale.h>
34#include <kdebug.h>
35#include <tdeglobalsettings.h>
36#include <tdecompletionbox.h>
37#include <knumvalidator.h>
38#include <kexiutils/longlongvalidator.h>
39#include <kexidb/field.h>
40#include <kexidb/fieldvalidator.h>
41
43class MyLineEdit : public KLineEdit
44{
45 public:
46 MyLineEdit(TQWidget *parent, const char *name) : KLineEdit(parent,name)
47 {}
48 protected:
49 virtual void drawFrame ( TQPainter * p ) {
50 p->setPen( TQPen( colorGroup().text() ) );
51 TQRect r = rect();
52 p->moveTo( r.topLeft() );
53 p->lineTo( r.topRight() );
54 p->lineTo( r.bottomRight() );
55 p->lineTo( r.bottomLeft() );
56 if (pos().x() == 0) //draw left side only when it is @ the edge
57 p->lineTo( r.topLeft() );
58 }
59};
60
61//======================================================
62
63KexiInputTableEdit::KexiInputTableEdit(KexiTableViewColumn &column, TQWidget *parent)
64 : KexiTableEdit(column, parent)
65{
66 setName("KexiInputTableEdit");
67// m_type = f.type(); //copied because the rest of code uses m_type
68// m_field = &f;
69// m_origValue = value;//original value
70 init();
71}
72
73KexiInputTableEdit::~KexiInputTableEdit()
74{
75}
76
77void KexiInputTableEdit::init()
78{
79// kdDebug() << "KexiInputTableEdit: m_origValue.typeName()==" << m_origValue.typeName() << endl;
80// kdDebug() << "KexiInputTableEdit: type== " << field()->typeName() << endl;
81// kdDebug() << "KexiInputTableEdit: displayed type== " << displayedField()->typeName() << endl;
82
83 m_textFormatter.setField( field() );
84
85 //init settings
86 m_decsym = TDEGlobal::locale()->decimalSymbol();
87 if (m_decsym.isEmpty())
88 m_decsym=".";//default
89
90 const bool align_right = displayedField()->isNumericType();
91
92 if (!align_right) {
93 //create layer for internal editor
94 TQHBoxLayout *lyr = new TQHBoxLayout(this);
95 lyr->addSpacing(4);
96 lyr->setAutoAdd(true);
97 }
98
99 //create internal editor
100 m_lineedit = new MyLineEdit(this, "KexiInputTableEdit-KLineEdit");
102 if (align_right)
103 m_lineedit->setAlignment(AlignRight);
104// m_cview->setFrame(false);
105// m_cview->setFrameStyle( TQFrame::Plain | TQFrame::Box );
106// m_cview->setLineWidth( 1 );
107 m_calculatedCell = false;
108
109#if 0 //js TODO
110 connect(m_cview->completionBox(), TQ_SIGNAL(activated(const TQString &)),
111 this, TQ_SLOT(completed(const TQString &)));
112 connect(m_cview->completionBox(), TQ_SIGNAL(highlighted(const TQString &)),
113 this, TQ_SLOT(completed(const TQString &)));
114 m_cview->completionBox()->setTabHandling(true);
115#endif
116
117}
118
119void KexiInputTableEdit::setValueInternal(const TQVariant& add, bool removeOld)
120{
121 TQString text( m_textFormatter.valueToText(removeOld ? TQVariant() : m_origValue, add.toString()) );
122 if (text.isEmpty()) {
123 if (m_origValue.toString().isEmpty()) {
124 //we have to set NULL initial value:
125 m_lineedit->setText(TQString());
126 }
127 }
128 else {
129 m_lineedit->setText(text);
130 }
131
132#if 0
133//move to end is better by default
134 m_cview->selectAll();
135#else
136//js TODO: by default we're moving to the end of editor, ADD OPTION allowing "select all chars"
137 m_lineedit->end(false);
138#endif
139
140 if (!m_lineedit->validator()) {
141 TQValidator *validator = new KexiDB::FieldValidator(
142 *field(), m_lineedit, "KexiInputTableEdit-validator");
143 m_lineedit->setValidator( validator );
144 }
145}
146
147#if 0
148//moved to KexiTextFormatter
149TQString KexiInputTableEdit::valueToText(KexiDB::Field* field, const TQVariant& value, const TQString& add)
150{
151 TQString text; //result
152
153 if (field->isFPNumericType()) {
156 text = TQString::number(value.toDouble(), 'f',
157 TQMAX(field->visibleDecimalPlaces(), 10)); //<-- 10 is quite good maximum for fractional digits
159 if (value.toDouble() == 0.0) {
160 text = add.isEmpty() ? "0" : add; //eat 0
161 }
162 else {
164 TQStringList sl = TQStringList::split(".", text);
165 if (text.isEmpty()) {
166 //nothing
167 }
168 else if (sl.count()==2) {
169// kdDebug() << "sl.count()=="<<sl.count()<< " " <<sl[0] << " | " << sl[1] << endl;
170 const TQString sl1 = sl[1];
171 int pos = sl1.length()-1;
172 if (pos>=1) {
173 for (;pos>=0 && sl1[pos]=='0';pos--)
174 ;
175 pos++;
176 }
177 if (pos>0)
178 text = sl[0] + m_decsym + sl1.left(pos);
179 else
180 text = sl[0]; //no decimal point
181 }
182 text += add;
183 }
184/*moved to KexiDB::FieldValidator
185 if (setValidator && !m_lineedit->validator()) {
186 TQValidator *validator = new KDoubleValidator(m_lineedit);
187 m_lineedit->setValidator( validator );
188 }*/
189 }
190 else {
191 text = value.toString();
192 if (field->isIntegerType()) {
193 if (value.toInt() == 0) {
194 text = add; //eat 0
195 }
196 else {
197 text += add;
198 }
199/*moved to KexiDB::FieldValidator
201 if (setValidator && !m_lineedit->validator()) {
202 TQValidator *validator;
203 if (KexiDB::Field::BigInteger == field()->type()) {
205 validator = new KexiUtils::LongLongValidator(m_lineedit);
206 }
207 else {
208 validator = new KIntValidator(m_lineedit);
209 }
210 m_lineedit->setValidator( validator );
211 }*/
212 }
213 else {//default: text
214 text += add;
215 }
216 }
217
218 return text;
219}
220#endif
221
222void KexiInputTableEdit::paintEvent ( TQPaintEvent * /*e*/ )
223{
224 TQPainter p(this);
225 p.setPen( TQPen( colorGroup().text() ) );
226 p.drawRect( rect() );
227}
228
229void
230KexiInputTableEdit::setRestrictedCompletion()
231{
232#if 0 //js TODO
233kdDebug() << "KexiInputTableEdit::setRestrictedCompletion()" << endl;
234// KLineEdit *content = static_cast<KLineEdit*>(m_view);
235 if(m_cview->text().isEmpty())
236 return;
237
238 kdDebug() << "KexiInputTableEdit::setRestrictedCompletion(): something to do" << endl;
239
240 m_cview->useGlobalKeyBindings();
241
242 TQStringList newC;
243 TQStringList::ConstIterator it, end( m_comp.constEnd() );
244 for( it = m_comp.constBegin(); it != end; ++it)
245 {
246 if((*it).startsWith(m_cview->text()))
247 newC.append(*it);
248 }
249 m_cview->setCompletedItems(newC);
250#endif
251}
252
253void
254KexiInputTableEdit::completed(const TQString &s)
255{
256// kdDebug() << "KexiInputTableEdit::completed(): " << s << endl;
257 m_lineedit->setText(s);
258}
259
261{
262 //not needed? if (m_lineedit->text()!=m_origValue.toString())
263 //not needed? return true;
265}
266
268{
269 return m_lineedit->text().isNull();
270}
271
273{
274 return !m_lineedit->text().isNull() && m_lineedit->text().isEmpty();
275}
276
278{
279 if (field()->isFPNumericType()) {//==KexiDB::Field::Double || m_type==KexiDB::Field::Float) {
281 TQString txt = m_lineedit->text();
282 if (m_decsym!=".")
283 txt = txt.replace(m_decsym,".");//convert back
284 bool ok;
285 const double result = txt.toDouble(&ok);
286 return ok ? TQVariant(result) : TQVariant();
287 }
288 else if (field()->isIntegerType()) {
290 bool ok;
291 if (KexiDB::Field::BigInteger == field()->type()) {
292 if (field()->isUnsigned()) {
293 const TQ_ULLONG result = m_lineedit->text().toULongLong(&ok);
294 return ok ? TQVariant(result) : TQVariant();
295 }
296 else {
297 const TQ_LLONG result = m_lineedit->text().toLongLong(&ok);
298 return ok ? TQVariant(result) : TQVariant();
299 }
300 }
301 if (KexiDB::Field::Integer == field()->type()) {
302 if (field()->isUnsigned()) {
303 const uint result = m_lineedit->text().toUInt(&ok);
304 return ok ? TQVariant(result) : TQVariant();
305 }
306 }
307 //default: signed int
308 const int result = m_lineedit->text().toInt(&ok);
309 return ok ? TQVariant(result) : TQVariant();
310 }
311 //default: text
312 return m_lineedit->text();
313}
314
315void
317{
318 m_lineedit->clear();
319}
320
322{
323 return m_lineedit->cursorPosition()==0;
324}
325
327{
328 return m_lineedit->cursorPosition()==(int)m_lineedit->text().length();
329}
330
332{
333 if (!m_lineedit)
334 return size();
335 return m_lineedit->size();
336}
337
338void KexiInputTableEdit::handleCopyAction(const TQVariant& value, const TQVariant& visibleValue)
339{
340 Q_UNUSED(visibleValue);
342 tqApp->clipboard()->setText( m_textFormatter.valueToText(value, TQString()) );
343}
344
345void KexiInputTableEdit::handleAction(const TQString& actionName)
346{
347 const bool alreadyVisible = m_lineedit->isVisible();
348
349 if (actionName=="edit_paste") {
350 if (!alreadyVisible) { //paste as the entire text if the cell was not in edit mode
351 emit editRequested();
352 m_lineedit->clear();
353 }
354 m_lineedit->paste();
355 }
356 else if (actionName=="edit_cut") {
358 if (!alreadyVisible) { //cut the entire text if the cell was not in edit mode
359 emit editRequested();
360 m_lineedit->selectAll();
361 }
362 m_lineedit->cut();
363 }
364}
365
366bool KexiInputTableEdit::showToolTipIfNeeded(const TQVariant& value, const TQRect& rect,
367 const TQFontMetrics& fm, bool focused)
368{
369 TQString text( value.type()==TQVariant::String ? value.toString()
370 : m_textFormatter.valueToText(value, TQString()) );
371 TQRect internalRect(rect);
372 internalRect.setLeft(rect.x()+leftMargin());
373 internalRect.setWidth(internalRect.width()-rightMargin(focused)-2*3);
374 kexidbg << rect << " " << internalRect << " " << fm.width(text) << endl;
375 return fm.width(text) > internalRect.width();
376}
377
379{
380 m_lineedit->end(false);
381}
382
384{
385 m_lineedit->home(false);
386}
387
389{
390 m_lineedit->selectAll();
391}
392
393KEXI_CELLEDITOR_FACTORY_ITEM_IMPL(KexiInputEditorFactoryItem, KexiInputTableEdit)
394
395#include "kexiinputtableedit.moc"
A validator for KexiDB data types.
Meta-data for a field.
Definition field.h:73
bool isFPNumericType() const
Definition field.h:266
bool isIntegerType() const
Definition field.h:259
bool isNumericType() const
Definition field.h:252
int visibleDecimalPlaces() const
Definition field.h:361
virtual TQVariant visibleValue()
General purpose cell editor using line edit widget.
virtual void moveCursorToEnd()
Implemented for KexiDataItemInterface.
virtual void moveCursorToStart()
Implemented for KexiDataItemInterface.
virtual void setValueInternal(const TQVariant &add, bool removeOld)
initializes this editor with add value
virtual void handleCopyAction(const TQVariant &value, const TQVariant &visibleValue)
virtual void clear()
clears item's data, so the data will contain NULL data
virtual void selectAll()
Implemented for KexiDataItemInterface.
KLineEdit * m_lineedit
orig. Line Edit's text after conversion - for easy comparing
virtual bool showToolTipIfNeeded(const TQVariant &value, const TQRect &rect, const TQFontMetrics &fm, bool focused)
virtual TQSize totalSize()
virtual TQVariant value()
virtual void handleAction(const TQString &actionName)
Abstract class for a cell editor. Handles cell painting and displaying the editor widget.
int leftMargin() const
virtual KexiDB::Field * field() const
Implemented for KexiDataItemInterface.
void setViewWidget(TQWidget *v)
KexiDB::Field * displayedField() const
int rightMargin(bool focused) const
void setField(KexiDB::Field *field)
Assigns field to the formatter. This affects its behaviour.
TQString valueToText(const TQVariant &value, const TQString &add) const