kexiformscrollview.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
3 Copyright (C) 2004-2006 Jaroslaw Staniek <js@iidea.pl>
4
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.
9
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.
14
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., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "kexiformscrollview.h"
22//#include "kexiformview.h"
23
24#include <formeditor/form.h>
25#include <formeditor/formmanager.h>
26#include <formeditor/objecttree.h>
27#include <formeditor/commands.h>
28#include <widget/utils/kexirecordmarker.h>
29
30#include <tdepopupmenu.h>
31#include <kdebug.h>
32
33KexiFormScrollView::KexiFormScrollView(TQWidget *parent, bool preview)
34 : KexiScrollView(parent, preview)
40{
41 m_currentLocalSortColumn = -1; /* no column */
42 m_localSortingOrder = -1; /* no sorting */
43 m_previousItem = 0;
44 m_navPanel = m_scrollViewNavPanel; //copy this pointer from KexiScrollView
45 if (preview) {
46 setRecordNavigatorVisible(true);
47//tmp
48// recordNavigator()->setEditingIndicatorEnabled(true);
49// recordNavigator()->showEditingIndicator(true);
50 }
51
52 connect(this, TQ_SIGNAL(resizingStarted()), this, TQ_SLOT(slotResizingStarted()));
53
54 m_popupMenu = new TDEPopupMenu(this, "contextMenu");
55
56// setFocusPolicy(NoFocus);
57}
58
59KexiFormScrollView::~KexiFormScrollView()
60{
61 if (m_owner)
62 delete m_data;
63 m_data = 0;
64}
65
66void
68{
69 KexiScrollView::show();
70
71#if 0 //moved to KexiFormView, OK?
72 //now get resize mode settings for entire form
73 if (m_preview) {
74 KexiFormView* fv = dynamic_cast<KexiFormView*>(parent());
75 int resizeMode = fv ? fv->resizeMode() : KexiFormView::ResizeAuto;
76 if (resizeMode == KexiFormView::ResizeAuto)
77 setResizePolicy(AutoOneFit);
78 }
79#endif
80}
81
82void
83KexiFormScrollView::slotResizingStarted()
84{
86 setSnapToGrid(KFormDesigner::FormManager::self()->snapWidgetsToGrid(), m_form->gridSize());
87 else
88 setSnapToGrid(false);
89}
90
92{
94 return 10;
95}
96
98{
99 //m_currentItem is already set by KexiDataAwareObjectInterface::setCursorPosition()
100 if (m_currentItem) {
104 }
105 }
106 else {
107 m_previousItem = 0;
108 }
109}
110
111void KexiFormScrollView::ensureCellVisible(int row, int col/*=-1*/)
112{
113 Q_UNUSED( row );
114 Q_UNUSED( col );
116// if (m_currentItem)
117 //fillDataItems(*m_currentItem);
118
119// if (m_form->tabStops()->first() && m_form->tabStops()->first()->widget())
120// m_form->tabStops()->first()->widget()->setFocus();
121}
122
124{
126 selectRow(r);
127}
128
130{
132 selectLastRow();
133}
134
136{
138 selectPrevRow();
139}
140
142{
144 selectNextRow();
145}
146
148{
150 selectFirstRow();
151}
152
154{
155 Q_UNUSED( repaint );
157}
158
159void KexiFormScrollView::addHeaderColumn(const TQString& caption, const TQString& description,
160 const TQIconSet& icon, int width)
161{
162 Q_UNUSED( caption );
163 Q_UNUSED( description );
164 Q_UNUSED( icon );
165 Q_UNUSED( width );
166
168}
169
171{
173 return m_localSortingOrder;
174}
175
177{
178 return m_currentLocalSortColumn;
179}
180
182{
184 m_currentLocalSortColumn = col;
185 m_localSortingOrder = order;
186}
187
189{
190 Q_UNUSED( col );
191 Q_UNUSED( order );
193}
194
199
200void KexiFormScrollView::createEditor(int row, int col, const TQString& addText,
201 bool removeOld)
202{
203 Q_UNUSED( row );
204 Q_UNUSED( addText );
205 Q_UNUSED( removeOld );
206
207 if (isReadOnly()) {
208 kexipluginsdbg << "KexiFormScrollView::createEditor(): DATA IS READ ONLY!"<<endl;
209 return;
210 }
211 if (column( col )->isReadOnly()) {
212 kexipluginsdbg << "KexiFormScrollView::createEditor(): COL IS READ ONLY!"<<endl;
213 return;
214 }
215
217 const bool startRowEdit = !m_rowEditing; //remember if we're starting row edit
218
219 if (!m_rowEditing) {
220 //we're starting row editing session
222
223 m_rowEditing = true;
224 //indicate on the vheader that we are editing:
228 //we should know that we are in state "new row editing"
229 m_newRowEditing = true;
230 //'insert' row editing: show another row after that:
231 m_data->append( m_insertItem );
232 //new empty insert item
233 m_insertItem = m_data->createItem(); //new KexiTableItem(dataColumns());
234// updateContents();
236 m_verticalHeader->addLabel();
237// m_verticalHeaderAlreadyAdded = true;
239 //refr. current and next row
240// updateContents(columnPos(0), rowPos(row), viewport()->width(), d->rowHeight*2);
241//js: warning this breaks behaviour (cursor is skipping, etc.): tqApp->processEvents(500);
242// ensureVisible(columnPos(m_curCol), rowPos(row+1)+d->rowHeight-1, columnWidth(m_curCol), d->rowHeight);
243
244// m_verticalHeader->setOffset(contentsY());
245 }
246 }
247
248 m_editor = editor(col); //m_dataItems.at(col);
249 if (!m_editor)
250 return;
251
252 if (startRowEdit) {
253 recordNavigator()->showEditingIndicator(true);
254// recordNavigator()->updateButtons(); //refresh 'next btn'
255
256 emit rowEditStarted(m_curRow);
257 }
258}
259
260KexiDataItemInterface *KexiFormScrollView::editor( int col, bool ignoreMissingEditor )
261{
262 Q_UNUSED( ignoreMissingEditor );
263
264 if (!m_data || col<0 || col>=columns())
265 return 0;
266
267 return dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
268// KexiFormDataItemInterface *item = m_dataItems.at(col);
269 //return item;
270
271/*
272 KexiTableViewColumn *tvcol = m_data->column(col);
273// int t = tvcol->field->type();
274
275 //find the editor for this column
276 KexiDataItemInterface *editor = d->editors[ tvcol ];
277 if (editor)
278 return editor;
279
280 //not found: create
281// editor = KexiCellEditorFactory::createEditor(*m_data->column(col)->field, this);
282 editor = KexiCellEditorFactory::createEditor(*m_data->column(col), this);
283 if (!editor) {//create error!
284 if (!ignoreMissingEditor) {
285 //js TODO: show error???
286 cancelRowEdit();
287 }
288 return 0;
289 }
290 editor->hide();
291 connect(editor,TQ_SIGNAL(editRequested()),this,TQ_SLOT(slotEditRequested()));
292 connect(editor,TQ_SIGNAL(cancelRequested()),this,TQ_SLOT(cancelEditor()));
293 connect(editor,TQ_SIGNAL(acceptRequested()),this,TQ_SLOT(acceptEditor()));
294
295 editor->resize(columnWidth(col)-1, rowHeight()-1);
296 editor->installEventFilter(this);
297 if (editor->widget())
298 editor->widget()->installEventFilter(this);
299 //store
300 d->editors.insert( tvcol, editor );
301 return editor;*/
302}
303
305{
306 Q_UNUSED( row );
307 Q_UNUSED( col );
309// if (m_currentItem)
310// m_provider->fillDataItems(*m_currentItem);
311}
312
313void KexiFormScrollView::updateCell(int row, int col)
314{
315 Q_UNUSED( row );
316 Q_UNUSED( col );
318}
319
323
325{
326 Q_UNUSED(row)
328}
329
334
339
344
346{
347 Q_UNUSED( item );
349}
350
351/*void KexiFormScrollView::slotAboutToDeleteRow(KexiTableItem& item,
352 KexiDB::ResultInfo* result, bool repaint)
353{
355}*/
356
357/*void KexiFormScrollView::slotRowDeleted()
358{
360}*/
361
362void KexiFormScrollView::slotRowInserted(KexiTableItem *item, bool repaint)
363{
364 Q_UNUSED( item );
365 Q_UNUSED( repaint );
367}
368
369void KexiFormScrollView::slotRowInserted(KexiTableItem *item, uint row, bool repaint)
370{
371 Q_UNUSED( item );
372 Q_UNUSED( row );
373 Q_UNUSED( repaint );
375}
376
377void KexiFormScrollView::slotRowsDeleted( const TQValueList<int> & )
378{
380}
381
382KexiDBForm* KexiFormScrollView::dbFormWidget() const
383{
384 return dynamic_cast<KexiDBForm*>(m_widget);
385}
386
388{
389 return dbFormWidget()->orderedDataAwareWidgets()->count(); //m_dataItems.count();
390}
391
392/*uint KexiFormScrollView::fieldNumberForColumn(int col)
393{
394 KexiFormDataItemInterface *item = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
395 if (!item)
396 return -1;
397 KexiFormDataItemInterfaceToIntMap::ConstIterator it(m_fieldNumbersForDataItems.find( item ));
398 return it!=m_fieldNumbersForDataItems.constEnd() ? it.data() : -1;
399}*/
400
402{
403 kexipluginsdbg << "KexiFormScrollView::columnEditable(" << col << ")" << endl;
404 foreach_list (TQPtrListIterator<KexiFormDataItemInterface>, it, m_dataItems) {
405 kexipluginsdbg << (dynamic_cast<TQWidget*>(it.current()) ? dynamic_cast<TQWidget*>(it.current())->name() : "" )
406 << " " << it.current()->dataSource() << endl;
407 }
408 kexipluginsdbg << "-- focus widgets --" << endl;
409 foreach_list (TQPtrListIterator<TQWidget>, it, *dbFormWidget()->orderedFocusWidgets()) {
410 kexipluginsdbg << it.current()->name() << endl;
411 }
412 kexipluginsdbg << "-- data-aware widgets --" << endl;
413 foreach_list (TQPtrListIterator<TQWidget>, it, *dbFormWidget()->orderedDataAwareWidgets()) {
414 kexipluginsdbg << it.current()->name() << endl;
415 }
416
417 //int index = dbFormWidget()->indexForDataItem( item );
418// KexiFormDataItemInterface *item1 = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedFocusWidgets()->at( col ));
419 KexiFormDataItemInterface *item = dynamic_cast<KexiFormDataItemInterface*>(dbFormWidget()->orderedDataAwareWidgets()->at( col ));
420
421 if (!item || item->isReadOnly())
422 return false;
423
424// KexiFormDataItemInterfaceToIntMap::ConstIterator it(m_fieldNumbersForDataItems.find( item ));
425// return KexiDataAwareObjectInterface::columnEditable( it!=m_fieldNumbersForDataItems.constEnd() ? it.data() : -1 );
427}
428
430{
431 if (!item)
432 return;
433 //only signal start editing when no row editing was started already
434 kexipluginsdbg << "** KexiFormScrollView::valueChanged(): editedItem="
435 << (dbFormWidget()->editedItem ? dbFormWidget()->editedItem->value().toString() : TQString())
436 << ", "
437 << (item ? item->value().toString() : TQString())
438 << endl;
439 if (dbFormWidget()->editedItem!=item) {
440 kexipluginsdbg << "**>>> dbFormWidget()->editedItem = dynamic_cast<KexiFormDataItemInterface*>(item)" << endl;
441 dbFormWidget()->editedItem = dynamic_cast<KexiFormDataItemInterface*>(item);
443 }
444 fillDuplicatedDataItems(dynamic_cast<KexiFormDataItemInterface*>(item), item->value());
445
446 //value changed: clear 'default value' mode (e.g. a blue italic text)
447 dynamic_cast<KexiFormDataItemInterface*>(item)->setDisplayDefaultValue(dynamic_cast<TQWidget*>(item), false);
448}
449
454
456{
458
459 if (m_preview) {
461 setRecordNavigatorVisible(m_data);
462 recordNavigator()->setEnabled(m_data);
463 if (m_data) {
464 recordNavigator()->setEditingIndicatorEnabled( !isReadOnly() );
465 recordNavigator()->showEditingIndicator(false);
466 }
467
468 dbFormWidget()->updateReadOnlyFlags();
469 }
470}
471
473{
474 const int id = fieldNumberForColumn(col);
475 return (id >= 0) ? m_data->column( id ) : 0;
476}
477
478bool KexiFormScrollView::shouldDisplayDefaultValueForItem(KexiFormDataItemInterface* itemIface) const
479{
480 return cursorAtNewRow()
481 && !itemIface->columnInfo()->field->defaultValue().isNull()
482//?? && (m_editor ? m_editor->value()==itemIface->columnInfo()->field->defaultValue() : true)
483 && !itemIface->columnInfo()->field->isAutoIncrement(); // default value defined
484}
485
487{
488 if (!dynamic_cast<KexiFormDataItemInterface*>(m_editor))
489 return false;
490
492 m_errorMessagePopup->close();
493
494 KexiFormDataItemInterface *itemIface = dynamic_cast<KexiFormDataItemInterface*>(m_editor);
495 itemIface->undoChanges();
496
497 const bool displayDefaultValue = shouldDisplayDefaultValueForItem(itemIface);
498 // now disable/enable "display default value" if needed (do it after setValue(), before setValue() turns it off)
499 if (itemIface->hasDisplayedDefaultValue() != displayDefaultValue)
500 itemIface->setDisplayDefaultValue( dynamic_cast<TQWidget*>(itemIface), displayDefaultValue );
501
502 fillDuplicatedDataItems(itemIface, m_editor->value());
503
504 // this will clear editor pointer and close message popup (if present)
506}
507
508void KexiFormScrollView::updateAfterCancelRowEdit()
509{
510 for (TQPtrListIterator<KexiFormDataItemInterface> it(m_dataItems); it.current(); ++it) {
511 if (dynamic_cast<TQWidget*>(it.current())) {
512 kexipluginsdbg << "KexiFormScrollView::updateAfterCancelRowEdit(): "
513 << dynamic_cast<TQWidget*>(it.current())->className() << " "
514 << dynamic_cast<TQWidget*>(it.current())->name() << endl;
515 }
516 KexiFormDataItemInterface *itemIface = it.current();
517 const bool displayDefaultValue = shouldDisplayDefaultValueForItem(itemIface);
518 itemIface->undoChanges();
519 if (itemIface->hasDisplayedDefaultValue() != displayDefaultValue)
520 itemIface->setDisplayDefaultValue( dynamic_cast<TQWidget*>(itemIface), displayDefaultValue );
521 }
522 recordNavigator()->showEditingIndicator(false);
523 dbFormWidget()->editedItem = 0;
524}
525
526void KexiFormScrollView::updateAfterAcceptRowEdit()
527{
528 if (!m_currentItem)
529 return;
530 recordNavigator()->showEditingIndicator(false);
531 dbFormWidget()->editedItem = 0;
532 //update visible data because there could be auto-filled (eg. autonumber) fields
535}
536
537void KexiFormScrollView::beforeSwitchView()
538{
539 m_editor = 0;
540}
541
543{
545 //only clear cmd history when KexiScrollView::refreshContentsSizeLater() has been called
546 if (!m_preview && sender()==&m_delayedResize) {
547 if (m_form)
548 m_form->clearCommandHistory();
549 }
550}
551
552void KexiFormScrollView::handleDataWidgetAction(const TQString& actionName)
553{
554 TQWidget *w = focusWidget();
556 while (w) {
557 item = dynamic_cast<KexiFormDataItemInterface*>(w);
558 if (item)
559 break;
560 w = w->parentWidget();
561 }
562 if (item)
563 item->handleAction(actionName);
564}
565
567{
568 handleDataWidgetAction("edit_copy");
569}
570
572{
573 handleDataWidgetAction("edit_cut");
574}
575
577{
578 handleDataWidgetAction("edit_paste");
579}
580
582{
584 return -1;
585}
586
587#include "kexiformscrollview.moc"
static FormManager * self()
Access to FormManager singleton.
void clearCommandHistory()
Definition form.cpp:411
A DB-aware form widget, acting as form's toplevel widget.
Definition kexidbform.h:44
KexiFormDataItemInterface * editedItem
Points to a currently edited data item.
Definition kexidbform.h:132
void updateReadOnlyFlags()
called from KexiFormScrollView::initDataContents()
bool isAutoIncrement() const
Definition field.h:231
TQVariant defaultValue() const
Definition field.h:326
The KexiDataAwareObjectInterface is an interface for record-based data object.
KexiTableItem * m_insertItem
item data for inserting
bool m_rowEditing
when (current or new) row is edited - changed field values are temporary stored here
TQGuardedPtr< KexiArrowTip > m_errorMessagePopup
KexiTableViewData * m_data
data structure displayed for this object
KexiDataItemInterface * editor() const
virtual void startEditCurrentCell(const TQString &setText=TQString())
KexiTableItem * m_currentItem
current data item
bool m_owner
true if m_data member is owned by this object
An interface for declaring widgets to be data-aware.
virtual bool isReadOnly() const
virtual TQVariant value()=0
virtual void handleAction(const TQString &actionName)
An interface for declaring form widgets to be data-aware.
virtual KexiDB::QueryColumnInfo * columnInfo() const
virtual void setDisplayDefaultValue(TQWidget *widget, bool displayDefaultValue)
virtual bool hasDisplayedDefaultValue() const
The KexiFormDataProvider class is a data provider for Kexi Forms.
void fillDuplicatedDataItems(KexiFormDataItemInterface *item, const TQVariant &value)
void fillDataItems(KexiTableItem &row, bool cursorAtNewRow)
The KexiFormEventHandler class handles events defined within Kexi Forms.
virtual void updateGUIAfterSorting()
Implementation for KexiDataAwareObjectInterface.
virtual bool columnEditable(int col)
virtual int currentLocalSortingOrder() const
Implementation for KexiDataAwareObjectInterface.
virtual int rowsPerPage() const
Implementation for KexiDataAwareObjectInterface.
virtual void cutSelection()
Cut current selection to a clipboard (e.g. cell)
virtual void addHeaderColumn(const TQString &caption, const TQString &description, const TQIconSet &icon, int width)
Implementation for KexiDataAwareObjectInterface.
virtual void updateRow(int row)
virtual void selectCellInternal()
Implementation for KexiDataAwareObjectInterface Called by KexiDataAwareObjectInterface::setCursorPosi...
virtual void updateWidgetScrollBars()
virtual void copySelection()
Copy current selection to a clipboard (e.g. cell)
virtual int currentLocalSortColumn() const
Implementation for KexiDataAwareObjectInterface.
virtual int lastVisibleRow() const
virtual bool cursorAtNewRow() const
virtual void setLocalSortingOrder(int col, int order)
Implementation for KexiDataAwareObjectInterface.
virtual void moveToRecordRequested(uint r)
virtual void updateCell(int row, int col)
virtual void updateWidgetContents()
virtual void paste()
Paste current clipboard contents (e.g. to a cell)
virtual void createEditor(int row, int col, const TQString &addText=TQString(), bool removeOld=false)
Implementation for KexiDataAwareObjectInterface.
virtual KexiTableViewColumn * column(int col)
void sortColumnInternal(int col, int order=0)
Implementation for KexiDataAwareObjectInterface.
virtual void clearColumnsInternal(bool repaint)
Implementation for KexiDataAwareObjectInterface.
virtual void editorShowFocus(int row, int col)
Implementation for KexiDataAwareObjectInterface.
virtual void moveToLastRecordRequested()
virtual int fieldNumberForColumn(int col)
virtual void refreshContentsSize()
virtual void slotRowInserted(KexiTableItem *item, bool repaint)
Handles KexiTableViewData::rowInserted() signal to repaint when needed.
virtual void moveToFirstRecordRequested()
virtual void valueChanged(KexiDataItemInterface *item)
Reimplemented from KexiFormDataProvider. Reaction for change of item.
virtual void slotRowRepaintRequested(KexiTableItem &item)
Handles KexiTableViewData::rowRepaintRequested() signal.
virtual void slotRowsDeleted(const TQValueList< int > &)
virtual void initDataContents()
virtual void updateWidgetContentsSize()
virtual int columns() const
KexiTableItem * m_previousItem
Used in selectCellInternal() to avoid fetching the same record twice.
virtual void ensureCellVisible(int row, int col)
Implementation for KexiDataAwareObjectInterface.
virtual void updateCurrentCell()
virtual void moveToNextRecordRequested()
virtual void moveToPreviousRecordRequested()
The KexiFormView lass provides a data-driven (record-based) form view .
void setEditRow(int row)
KexiRecordNavigatorHandler interface handles requests generated by KexiRecordNavigator.
void showEditingIndicator(bool show)
void setEditingIndicatorEnabled(bool set)
The scrollview which includes KexiDBForm.
virtual void refreshContentsSize()
The KexiSharedActionClient is an interface using application-wide (shared) actions.