1
/* This file is part of the KDE project
2
Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
3
Copyright (C) 2004-2009 Jarosław Staniek <staniek@kde.org>
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.
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.
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.
21
#include "kexidblineedit.h"
22
#include "kexidbautofield.h"
27
#include <KIconEffect>
32
#include <QPaintEvent>
34
#include <QStyleOption>
36
#include <kexiutils/utils.h>
37
#include <kexiutils/styleproxy.h>
38
#include <kexidb/queryschema.h>
39
#include <kexidb/fieldvalidator.h>
40
#include <kexiutils/utils.h>
42
//! @todo reenable as an app aption
43
//#define USE_KLineEdit_setReadOnly
45
//! @internal A validator used for read only flag to disable editing
46
class KexiDBLineEdit_ReadOnlyValidator : public QValidator
49
KexiDBLineEdit_ReadOnlyValidator(QObject * parent)
50
: QValidator(parent) {
52
~KexiDBLineEdit_ReadOnlyValidator() {}
53
virtual State validate(QString &, int &) const {
60
//! A style proxy overriding KexiDBLineEdit style
61
class KexiDBLineEditStyle : public KexiUtils::StyleProxy
64
KexiDBLineEditStyle(QStyle* parentStyle) : KexiUtils::StyleProxy(parentStyle), indent(0)
68
void setIndent(int indent) {
69
this->indent = indent;
72
QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
74
const KFormDesigner::FormWidgetInterface *formWidget = dynamic_cast<const KFormDesigner::FormWidgetInterface*>(widget);
75
if (formWidget->designMode()) {
76
const KexiFormDataItemInterface *dataItemIface = dynamic_cast<const KexiFormDataItemInterface*>(widget);
77
if (dataItemIface && !dataItemIface->dataSource().isEmpty() && !formWidget->editingMode()) {
78
if (element == SE_LineEditContents) {
79
QRect rect = KexiUtils::StyleProxy::subElementRect(SE_LineEditContents, option, widget);
80
if (option->direction == Qt::LeftToRight)
81
return rect.adjusted(indent, 0, 0, 0);
83
return rect.adjusted(0, 0, -indent, 0);
87
return KexiUtils::StyleProxy::subElementRect(element, option, widget);
94
KexiDBLineEdit::KexiDBLineEdit(QWidget *parent)
96
, KexiDBTextWidgetInterface()
97
, KexiFormDataItemInterface()
98
, m_readWriteValidator(0)
99
, m_menuExtender(this, this)
100
, m_internalReadOnly(false)
101
, m_slotTextChanged_enabled(true)
103
#ifdef USE_KLineEdit_setReadOnly
104
//! @todo reenable as an app aption
105
QPalette p(widget->palette());
106
p.setColor(KexiFormUtils::lighterGrayBackgroundColor(palette()));
107
widget->setPalette(p);
111
tmpFont.setPointSize(KGlobalSettings::smallestReadableFont().pointSize());
112
setMinimumHeight(QFontMetrics(tmpFont).height() + 6);
113
connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged(const QString&)));
115
KexiDBLineEditStyle *ks = new KexiDBLineEditStyle(style());
117
ks->setIndent(KexiFormUtils::dataSourceTagIcon().width());
121
KexiDBLineEdit::~KexiDBLineEdit()
126
void FormWidgetInterface::setDesignMode(bool design)
128
FormWidgetInterface::setDesignMode(design);
129
setCursor(design ? QCursor(Qt::ArrowCursor) : QCursor());
132
void KexiDBLineEdit::setInvalidState(const QString& displayText)
134
KLineEdit::setReadOnly(true);
135
//! @todo move this to KexiDataItemInterface::setInvalidStateInternal() ?
136
if (focusPolicy() & Qt::TabFocus)
137
setFocusPolicy(Qt::ClickFocus);
138
setText(displayText);
141
void KexiDBLineEdit::setValueInternal(const QVariant& add, bool removeOld)
143
m_slotTextChanged_enabled = false;
144
setText( m_textFormatter.valueToText(removeOld ? QVariant() : m_origValue, add.toString()) );
145
setCursorPosition(0); //ok?
146
m_slotTextChanged_enabled = true;
149
QVariant KexiDBLineEdit::value()
151
return m_textFormatter.textToValue( text() );
154
void KexiDBLineEdit::slotTextChanged(const QString&)
156
if (!m_slotTextChanged_enabled)
158
signalValueChanged();
161
bool KexiDBLineEdit::valueIsNull()
163
return valueIsEmpty(); //ok??? text().isNull();
166
bool KexiDBLineEdit::valueIsEmpty()
168
return m_textFormatter.valueIsEmpty( text() );
171
bool KexiDBLineEdit::valueIsValid()
173
return m_textFormatter.valueIsValid( text() );
176
bool KexiDBLineEdit::isReadOnly() const
178
return m_internalReadOnly;
181
void KexiDBLineEdit::setReadOnly(bool readOnly)
183
#ifdef USE_KLineEdit_setReadOnly
184
//! @todo reenable as an app aption
185
return KLineEdit::setReadOnly(readOnly);
187
m_internalReadOnly = readOnly;
188
if (m_internalReadOnly) {
189
if (m_readWriteValidator)
190
disconnect(m_readWriteValidator, SIGNAL(destroyed(QObject*)),
191
this, SLOT(slotReadWriteValidatorDestroyed(QObject*)));
192
m_readWriteValidator = validator();
193
if (m_readWriteValidator)
194
connect(m_readWriteValidator, SIGNAL(destroyed(QObject*)),
195
this, SLOT(slotReadWriteValidatorDestroyed(QObject*)));
196
if (!m_readOnlyValidator)
197
m_readOnlyValidator = new KexiDBLineEdit_ReadOnlyValidator(this);
198
setValidator(m_readOnlyValidator);
200
//revert to r/w validator
201
setValidator(m_readWriteValidator);
203
m_menuExtender.updatePopupMenuActions();
207
void KexiDBLineEdit::slotReadWriteValidatorDestroyed(QObject*)
209
m_readWriteValidator = 0;
212
QMenu * KexiDBLineEdit::createPopupMenu()
214
QMenu *contextMenu = KLineEdit::createStandardContextMenu();
215
m_menuExtender.createTitle(contextMenu);
220
QWidget* KexiDBLineEdit::widget()
225
bool KexiDBLineEdit::cursorAtStart()
227
return cursorPosition() == 0;
230
bool KexiDBLineEdit::cursorAtEnd()
232
return cursorPosition() == (int)text().length();
235
void KexiDBLineEdit::clear()
237
if (!m_internalReadOnly)
241
void KexiDBLineEdit::setColumnInfo(KexiDB::QueryColumnInfo* cinfo)
243
KexiFormDataItemInterface::setColumnInfo(cinfo);
244
m_textFormatter.setField( cinfo ? cinfo->field : 0 );
249
//! @todo handle input mask (via QLineEdit::setInputMask()) using a special KexiDB::FieldInputMask class
250
setValidator(new KexiDB::FieldValidator(*cinfo->field, this));
252
const QString inputMask(m_textFormatter.inputMask());
253
if (!inputMask.isEmpty())
254
setInputMask(inputMask);
256
KexiDBTextWidgetInterface::setColumnInfo(cinfo, this);
260
void KexiDBLineEdit::paint( QPainter *p )
262
KexiDBTextWidgetInterface::paint( this, &p, text().isEmpty(), alignment(), hasFocus() );
265
void KexiDBLineEdit::paintEvent(QPaintEvent *pe)
267
KLineEdit::paintEvent(pe);
268
KFormDesigner::FormWidgetInterface *formWidget = dynamic_cast<KFormDesigner::FormWidgetInterface*>(this);
269
if (formWidget->designMode()) {
270
KexiFormDataItemInterface *dataItemIface = dynamic_cast<KexiFormDataItemInterface*>(this);
271
if (dataItemIface && !dataItemIface->dataSource().isEmpty() && !formWidget->editingMode()) {
272
// draw "data source tag" icon
274
QStyleOptionFrameV2 option;
275
initStyleOption(&option);
277
int leftMargin, topMargin, rightMargin, bottomMargin;
278
getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
279
QRect r( style()->subElementRect(QStyle::SE_LineEditContents, &option, this) );
280
r.setX(r.x() + leftMargin);
281
r.setY(r.y() + topMargin);
282
r.setRight(r.right() - rightMargin);
283
r.setBottom(r.bottom() - bottomMargin);
284
QPixmap dataSourceTagIcon;
286
if (layoutDirection() == Qt::LeftToRight) {
287
dataSourceTagIcon = KexiFormUtils::dataSourceTagIcon();
288
x = r.left() - dataSourceTagIcon.width() + 2;
291
dataSourceTagIcon = KexiFormUtils::dataSourceRTLTagIcon();
295
x, r.top() + (r.height() - dataSourceTagIcon.height()) / 2,
302
bool KexiDBLineEdit::event(QEvent * e)
304
const bool ret = KLineEdit::event(e);
305
KexiDBTextWidgetInterface::event(e, this, text().isEmpty());
306
if (e->type() == QEvent::FocusOut) {
307
QFocusEvent *fe = static_cast<QFocusEvent *>(e);
308
if (fe->reason() == Qt::TabFocusReason || fe->reason() == Qt::BacktabFocusReason) {
309
//display aligned to left after loosing the focus (only if this is tab/backtab event)
310
//! @todo add option to set cursor at the beginning
311
setCursorPosition(0); //ok?
317
bool KexiDBLineEdit::appendStretchRequired(KexiDBAutoField* autoField) const
319
return KexiDBAutoField::Top == autoField->labelPosition();
322
void KexiDBLineEdit::handleAction(const QString& actionName)
324
if (actionName == "edit_copy") {
326
} else if (actionName == "edit_paste") {
328
} else if (actionName == "edit_cut") {
334
void KexiDBLineEdit::setDisplayDefaultValue(QWidget *widget, bool displayDefaultValue)
336
KexiFormDataItemInterface::setDisplayDefaultValue(widget, displayDefaultValue);
337
// initialize display parameters for default / entered value
338
KexiDisplayUtils::DisplayParameters * const params = displayDefaultValue
339
? m_displayParametersForDefaultValue : m_displayParametersForEnteredValue;
340
setFont(params->font);
341
QPalette pal(palette());
342
pal.setColor(QPalette::Active, QColorGroup::Text, params->textColor);
346
void KexiDBLineEdit::undo()
351
void KexiDBLineEdit::moveCursorToEnd()
353
KLineEdit::end(false/*!mark*/);
356
void KexiDBLineEdit::moveCursorToStart()
358
KLineEdit::home(false/*!mark*/);
361
void KexiDBLineEdit::selectAll()
363
KLineEdit::selectAll();
366
bool KexiDBLineEdit::keyPressed(QKeyEvent *ke)
372
void KexiDBLineEdit::updateTextForDataSource()
376
setText(dataSource());
379
void KexiDBLineEdit::setDataSource(const QString &ds)
381
KexiFormDataItemInterface::setDataSource(ds);
382
updateTextForDataSource();
385
void KexiDBLineEdit::setDataSourcePartClass(const QString &partClass)
387
KexiFormDataItemInterface::setDataSourcePartClass(partClass);
388
updateTextForDataSource();
391
#include "kexidblineedit.moc"