1
/* This file is part of the KDE project
2
Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3
Copyright (C) 2004-2005 Jaroslaw Staniek <js@iidea.pl>
5
This library 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 library 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 library; see the file COPYING.LIB. If not, write to
17
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
Boston, MA 02111-1307, USA.
21
#include <qpopupmenu.h>
22
#include <qscrollview.h>
26
#include <kgenericfactory.h>
29
#include <kiconloader.h>
30
#include <knumvalidator.h>
33
#include <container.h>
36
#include <formmanager.h>
37
#include <objecttree.h>
38
#include <formeditor/utils.h>
39
#include <kexidb/utils.h>
40
#include <kexidb/connection.h>
42
#include <widgetlibrary.h>
43
#include <kexigradientwidget.h>
44
#include <kexi_utils.h>
45
#include <keximainwindow.h>
47
#include "kexidbform.h"
48
#include "kexiformview.h"
49
#include "kexilabel.h"
50
#include "kexidbinputwidget.h"
51
#include "kexidataawarewidgetinfo.h"
53
#include "kexidbfactory.h"
55
#define KEXI_NO_KexiDBInputWidget //temp. for 0.1
58
KexiSubForm::KexiSubForm(Form *parentForm, QWidget *parent, const char *name)
59
: QScrollView(parent, name), m_parentForm(parentForm), m_form(0), m_widget(0)
61
setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
62
viewport()->setPaletteBackgroundColor(colorGroup().mid());
66
KexiSubForm::paintEvent(QPaintEvent *ev)
68
QScrollView::paintEvent(ev);
71
setWFlags(WPaintUnclipped);
73
QString txt("Subform");
75
f.setPointSize(f.pointSize() * 3);
77
const int txtw = fm.width(txt), txth = fm.height();
82
p.drawText(width()/2, height()/2, txt, Qt::AlignCenter|Qt::AlignVCenter);
85
clearWFlags( WPaintUnclipped );
89
KexiSubForm::setFormName(const QString &name)
94
m_formName = name; //assign, even if the name points to nowhere
103
QWidget *pw = parentWidget();
104
KexiFormView *view = 0;
107
if(pw->isA("KexiSubForm")) {
108
if(list.contains(pw->name())) {
109
//! @todo error message
110
return; // Be sure to don't run into a endless-loop cause of recursive subforms.
112
list.append(pw->name());
114
else if(! view && pw->isA("KexiFormView"))
115
view = static_cast<KexiFormView*>(pw); // we need a KexiFormView*
116
pw = pw->parentWidget();
119
if (!view || !view->parentDialog() || !view->parentDialog()->mainWin()
120
|| !view->parentDialog()->mainWin()->project()->dbConnection())
123
KexiDB::Connection *conn = view->parentDialog()->mainWin()->project()->dbConnection();
125
// we check if there is a form with this name
126
int id = KexiDB::idForObjectName(*conn, name, KexiPart::FormObjectType);
127
if((id == 0) || (id == view->parentDialog()->id())) // == our form
128
return; // because of recursion when loading
130
// we create the container widget
132
m_widget = new KexiDBFormBase(viewport(), "kexisubform_widget");
135
m_form = new Form(m_parentForm->manager(), this->name());
136
m_form->createToplevel(m_widget);
138
// and load the sub form
140
bool ok = conn->loadDataBlock(id, data, QString::null);
142
ok = KFormDesigner::FormIO::loadFormFromString(m_form, m_widget, data);
147
m_formName = QString::null;
150
m_form->setDesignMode(false);
152
// Install event filters on the whole newly created form
153
KFormDesigner::ObjectTreeItem *tree = m_parentForm->objectTree()->lookup(QObject::name());
154
KFormDesigner::installRecursiveEventFilter(this, tree->eventEater());
159
//////////////////////////////////////////
161
KexiDBLineEdit::KexiDBLineEdit(QWidget *parent, const char *name)
162
: KLineEdit(parent, name)
163
, KexiFormDataItemInterface()
165
connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged(const QString&)));
168
KexiDBLineEdit::~KexiDBLineEdit()
172
void KexiDBLineEdit::setInvalidState( const QString& displayText )
175
//! @todo move this to KexiDataItemInterface::setInvalidStateInternal() ?
176
if (focusPolicy() & TabFocus)
177
setFocusPolicy(QWidget::ClickFocus);
178
setText(displayText);
181
void KexiDBLineEdit::setValueInternal(const QVariant& add, bool removeOld)
183
if (m_field->type()==KexiDB::Field::Boolean) {
184
//! @todo temporary solution for booleans!
185
setText( add.toBool() ? "1" : "0" );
189
setText( add.toString() );
191
setText( m_origValue.toString() + add.toString() );
196
QVariant KexiDBLineEdit::value()
201
void KexiDBLineEdit::slotTextChanged(const QString&)
203
signalValueChanged();
206
bool KexiDBLineEdit::valueIsNull()
208
return text().isNull();
211
bool KexiDBLineEdit::valueIsEmpty()
213
return text().isEmpty();
216
bool KexiDBLineEdit::isReadOnly() const
218
return KLineEdit::isReadOnly();
221
QWidget* KexiDBLineEdit::widget()
226
bool KexiDBLineEdit::cursorAtStart()
228
return cursorPosition()==0;
231
bool KexiDBLineEdit::cursorAtEnd()
233
return cursorPosition()==(int)text().length();
236
void KexiDBLineEdit::clear()
238
setText(QString::null);
241
void KexiDBLineEdit::setField(KexiDB::Field* field)
243
KexiFormDataItemInterface::setField(field);
246
//! @todo merge this code with KexiTableEdit code!
247
//! @todo set maximum length validator
248
//! @todo handle input mask (via QLineEdit::setInputMask()
249
const KexiDB::Field::Type t = field->type();
250
if (field->isIntegerType()) {
251
QValidator *validator = 0;
252
const bool u = field->isUnsigned();
254
if (t==KexiDB::Field::Byte) {
255
bottom = u ? 0 : -0x80;
256
top = u ? 0xff : 0x7f;
258
else if (t==KexiDB::Field::ShortInteger) {
259
bottom = u ? 0 : -0x8000;
260
top = u ? 0xffff : 0x7fff;
262
else if (t==KexiDB::Field::Integer) {
263
bottom = u ? 0 : -0x7fffffff-1;
264
top = u ? 0xffffffff : 0x7fffffff;
266
else if (t==KexiDB::Field::BigInteger) {
267
/*! @todo couldn't work with KIntValidator: implement lonlong validator!
268
bottom = u ? 0 : -0x7fffffffffffffff;
269
top = u ? 0xffffffffffffffff : 127;*/
270
validator = new KIntValidator(this);
274
validator = new KIntValidator(bottom, top, this);
275
setValidator( validator );
277
else if (field->isFPNumericType()) {
278
QValidator *validator;
279
if (t==KexiDB::Field::Float) {
280
if (field->isUnsigned()) //ok?
281
validator = new KDoubleValidator(0, 3.4e+38, field->scale(), this);
283
validator = new KDoubleValidator(this);
286
if (field->isUnsigned()) //ok?
287
validator = new KDoubleValidator(0, 1.7e+308, field->scale(), this);
289
validator = new KDoubleValidator(this);
291
setValidator( validator );
293
else if (t==KexiDB::Field::Date) {
294
//! @todo use KDateWidget
295
QValidator *validator = new KDateValidator(this);
296
setValidator( validator );
298
else if (t==KexiDB::Field::Time) {
299
//! @todo use KTimeWidget
300
setInputMask("00:00:00");
302
else if (t==KexiDB::Field::Boolean) {
303
//! @todo temporary solution for booleans!
304
QValidator *validator = new KIntValidator(0, 1, this);
305
setValidator( validator );
310
//////////////////////////////////////////
312
KexiPushButton::KexiPushButton( const QString & text, QWidget * parent, const char * name )
313
: KPushButton(text, parent, name)
317
KexiPushButton::~KexiPushButton()
321
//////////////////////////////////////////
323
KexiDBFactory::KexiDBFactory(QObject *parent, const char *name, const QStringList &)
324
: KFormDesigner::WidgetFactory(parent, name)
326
// KFormDesigner::WidgetInfo *wView = new KFormDesigner::WidgetInfo(this);
327
KexiDataAwareWidgetInfo *wView = new KexiDataAwareWidgetInfo(this);
328
wView->setPixmap("form");
329
wView->setClassName("KexiDBForm");
330
wView->setName(i18n("Database Form"));
331
wView->setNamePrefix("DBForm");
332
wView->setDescription(i18n("A db-aware form widget"));
335
KexiDataAwareWidgetInfo *wSubForm = new KexiDataAwareWidgetInfo(this);
336
wSubForm->setPixmap("form");
337
wSubForm->setClassName("KexiSubForm");
338
wSubForm->setName(i18n("Sub Form"));
339
wSubForm->setNamePrefix("SubForm");
340
wSubForm->setDescription(i18n("A form widget included in another Form"));
341
wSubForm->setAutoSyncForProperty( "formName", false );
344
// KexiDataAwareWidgetInfo *wLineEdit = new KexiDataAwareWidgetInfo(this);
346
KFormDesigner::WidgetInfo *wLineEdit = new KFormDesigner::WidgetInfo(
347
this, "stdwidgets", "KLineEdit");
348
wLineEdit->setPixmap("lineedit");
349
wLineEdit->setClassName("KexiDBLineEdit");
350
wLineEdit->addAlternateClassName("QLineEdit", true/*override*/);
351
wLineEdit->addAlternateClassName("KLineEdit", true/*override*/);
352
wLineEdit->setIncludeFileName("klineedit.h");
353
wLineEdit->setName(i18n("Line Edit"));
354
wLineEdit->setNamePrefix("LineEdit");
355
wLineEdit->setDescription(i18n("A widget to input text"));
358
/* @todo allow to inherit from stdwidgets' KLineEdit */
359
KexiDataAwareWidgetInfo *wLabel = new KexiDataAwareWidgetInfo(this);
360
wLabel->setPixmap("label");
361
wLabel->setClassName("KexiLabel");
362
wLabel->addAlternateClassName("QLabel", true/*override*/);
363
wLabel->setIncludeFileName("qlabel.h");
364
wLabel->setName(i18n("Text Label"));
365
wLabel->setNamePrefix("TextLabel");
366
wLabel->setDescription(i18n("A widget to display text"));
369
#ifndef KEXI_NO_KexiDBInputWidget
371
KexiDataAwareWidgetInfo *wInput = new KexiDataAwareWidgetInfo(this);
372
wInput->setPixmap("edit");
373
wInput->setClassName("KexiDBInputWidget");
374
wInput->addAlternateClassName("QLabel", true);
375
//todo wInput->addAlternateClassName("QLineEdit", true);
376
//todo wInput->addAlternateClassName("KLineEdit", true);
377
//todo wInput->addAlternateClassName("KexiDBLineEdit", true); //for compat.
378
wInput->setIncludeFileName("qlabel.h");
379
wInput->setName(i18n("Input Widget"));
380
wInput->setNamePrefix(
381
i18n("Widget name. This string will be used to name widgets of this class. It must _not_ contain white spaces and non latin1 characters", "inputWidget"));
382
// wInput->setDescription(i18n("A super-duper widget"));
387
KFormDesigner::WidgetInfo *wPushButton = new KFormDesigner::WidgetInfo(
388
this, "stdwidgets", "KPushButton");
389
wPushButton->addAlternateClassName("KexiPushButton");
390
addClass(wPushButton);
392
m_propDesc["dataSource"] = i18n("Data Source");
393
m_propDesc["formName"] = i18n("Form Name");
394
m_propDesc["onClickAction"] = i18n("On Click");
396
#ifdef KEXI_NO_UNFINISHED
397
//we don't want not-fully implemented/usable classes:
398
hideClass("KexiPictureLabel");
399
hideClass("KIntSpinBox");
400
hideClass("KComboBox");
404
KexiDBFactory::~KexiDBFactory()
409
KexiDBFactory::create(const QCString &c, QWidget *p, const char *n, KFormDesigner::Container *container)
411
kexipluginsdbg << "KexiDBFactory::create() " << this << endl;
414
QString text = container->form()->manager()->lib()->textForWidgetName(n, c);
416
if(c == "KexiSubForm")
418
w = new KexiSubForm(container->form(), p, n);
420
else if(c == "KexiDBLineEdit")
422
w = new KexiDBLineEdit(p, n);
423
w->setCursor(QCursor(Qt::ArrowCursor));
425
else if(c == "KexiLabel")
427
w = new KexiLabel(text, p, n);
429
else if(c == "KexiDBInputWidget") //todo: || c == "KexiDBLineEdit"/*for compatibility*/)
431
w = new KexiDBInputWidget(p, n);
433
else if(c == "KPushButton" || c == "KexiPushButton")
434
w = new KexiPushButton(text, p, n);
440
KexiDBFactory::createMenuActions(const QCString &classname, QWidget *w, QPopupMenu *menu,
441
KFormDesigner::Container *)
443
if(classname == "QPushButton" || classname == "KPushButton" || classname == "KexiPushButton")
445
/*! @todo also call createMenuActions() for inherited factory! */
446
m_assignAction->plug( menu );
453
KexiDBFactory::createCustomActions(KActionCollection* col)
455
//this will create shared instance action for design mode (special collection is provided)
456
m_assignAction = new KAction( i18n("Assign Action..."), SmallIconSet("form_action"),
457
0, 0, 0, col, "widget_assign_action");
460
/*KexiDBFactory::assignAction()
462
emit executeCustomAction("assignAction", m_widget);
466
KexiDBFactory::startEditing(const QCString &classname, QWidget *w, KFormDesigner::Container *container)
468
m_container = container;
470
#warning Is there any reason to edit a lineedit in design-mode?
472
if(classname == "KexiDBLineEdit")
474
//! @todo this code should not be copied here but
475
//! just inherited StdWidgetFactory::clearWidgetContent() should be called
476
KLineEdit *lineedit = static_cast<KLineEdit*>(w);
477
createEditor(classname, lineedit->text(), lineedit, container,
478
lineedit->geometry(), lineedit->alignment(), true);
481
else if ( classname == "KexiLabel" ) {
482
KexiLabel *label = static_cast<KexiLabel*>(w);
484
if(label->textFormat() == RichText)
486
QString text = label->text();
487
if ( editRichText( label, text ) )
489
changeProperty( "textFormat", "RichText", container );
490
changeProperty( "text", text, container );
493
if ( classname == "KexiLabel" )
494
w->resize(w->sizeHint());
498
createEditor(classname, label->text(), label, container,
499
label->geometry(), label->alignment());
503
else if (classname == "KexiSubForm") {
504
// open the form in design mode
505
KexiMainWindow *mainWin = Kexi::findParent<KexiMainWindow>(w, "KexiMainWindow");
506
KexiSubForm *subform = static_cast<KexiSubForm*>(w);
508
mainWin->openObject("kexi/form", subform->formName(), Kexi::DesignViewMode);
515
KexiDBFactory::previewWidget(const QCString &, QWidget *, KFormDesigner::Container *)
521
KexiDBFactory::clearWidgetContent(const QCString &classname, QWidget *w)
523
//! @todo this code should not be copied here but
524
//! just inherited StdWidgetFactory::clearWidgetContent() should be called
525
if(classname == "KexiDBLineEdit")
526
static_cast<KLineEdit*>(w)->clear();
527
if(classname == "KexiLabel")
528
static_cast<QLabel*>(w)->clear();
535
KexiDBFactory::autoSaveProperties(const QCString &classname)
537
QValueList<QCString> lst;
538
// if(classname == "KexiSubForm")
540
// if(classname == "KexiDBLineEdit")
541
// return QStringList("dataSource");
546
KexiDBFactory::isPropertyVisibleInternal(const QCString& classname, QWidget *,
547
const QCString& property)
549
if(classname == "KexiPushButton") {
550
return property!="isDragEnabled"
551
#ifdef KEXI_NO_UNFINISHED
552
&& property!="onClickAction" /*! @todo reenable */
553
&& property!="iconSet" /*! @todo reenable */
554
&& property!="stdItem" /*! @todo reenable stdItem */
558
else if(classname == "KexiDBLineEdit")
559
return property!="urlDropsEnabled"
560
#ifdef KEXI_NO_UNFINISHED
561
&& property!="inputMask"
562
&& property!="maxLength" //!< we may want to integrate this with db schema
565
else if(classname == "KexiSubForm")
566
return property!="dragAutoScroll"
567
&& property!="resizePolicy"
568
&& property!="focusPolicy";
569
else if(classname == "KexiDBForm")
570
return property!="iconText";
571
else if(classname == "KexiLabel")
572
return property!="focusPolicy";
577
K_EXPORT_COMPONENT_FACTORY(kexidbwidgets, KGenericFactory<KexiDBFactory>("kexidbwidgets"))
579
#include "kexidbfactory.moc"