fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / dbaccess / source / ui / tabledesign / TEditControl.cxx
blobba648963ba8531b713683aa488673b98e20a4431
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "TEditControl.hxx"
21 #include <comphelper/processfactory.hxx>
22 #include <tools/debug.hxx>
23 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
24 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
25 #include <com/sun/star/sdbcx/XAlterTable.hpp>
26 #include <com/sun/star/sdbcx/XDrop.hpp>
27 #include <com/sun/star/sdbcx/XAppend.hpp>
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <com/sun/star/util/XNumberFormatTypes.hpp>
30 #include "dbu_tbl.hrc"
31 #include "dbustrings.hrc"
32 #include "browserids.hxx"
33 #include "dbaccess_helpid.hrc"
34 #include <comphelper/types.hxx>
35 #include "FieldDescControl.hxx"
36 #include "FieldDescriptions.hxx"
37 #include <vcl/msgbox.hxx>
38 #include "TableUndo.hxx"
39 #include "TableController.hxx"
40 #include <connectivity/dbtools.hxx>
41 #include "SqlNameEdit.hxx"
42 #include "TableRowExchange.hxx"
43 #include <sot/storage.hxx>
44 #include "UITools.hxx"
45 #include "TableFieldControl.hxx"
46 #include "dsntypes.hxx"
48 #include "dbaccess_slotid.hrc"
50 using namespace ::dbaui;
51 using namespace ::comphelper;
52 using namespace ::svt;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::container;
55 using namespace ::com::sun::star::io;
56 using namespace ::com::sun::star::beans;
57 using namespace ::com::sun::star::frame;
58 using namespace ::com::sun::star::util;
59 using namespace ::com::sun::star::lang;
60 using namespace ::com::sun::star::sdbc;
61 using namespace ::com::sun::star::sdbcx;
62 using namespace ::com::sun::star::sdb;
64 // TYPEINIT1(OTableEditorCtrl, DBView);
66 #define HANDLE_ID 0
68 // default field widths
69 #define FIELDNAME_WIDTH 100
70 #define FIELDTYPE_WIDTH 150
71 #define FIELDDESCR_WIDTH 300
73 // Maximum length in description field
74 #define MAX_DESCR_LEN 256
76 OTableEditorCtrl::ClipboardInvalidator::ClipboardInvalidator(sal_uLong nTimeout,OTableEditorCtrl* _pOwner)
77 : m_pOwner(_pOwner)
80 m_aInvalidateTimer.SetTimeout(nTimeout);
81 m_aInvalidateTimer.SetTimeoutHdl(LINK(this, OTableEditorCtrl::ClipboardInvalidator, OnInvalidate));
82 m_aInvalidateTimer.Start();
85 OTableEditorCtrl::ClipboardInvalidator::~ClipboardInvalidator()
87 m_aInvalidateTimer.Stop();
90 void OTableEditorCtrl::ClipboardInvalidator::Stop()
92 m_aInvalidateTimer.Stop();
95 IMPL_LINK_NOARG_TYPED(OTableEditorCtrl::ClipboardInvalidator, OnInvalidate, Timer *, void)
97 m_pOwner->GetView()->getController().InvalidateFeature(SID_CUT);
98 m_pOwner->GetView()->getController().InvalidateFeature(SID_COPY);
99 m_pOwner->GetView()->getController().InvalidateFeature(SID_PASTE);
102 void OTableEditorCtrl::Init()
104 OTableRowView::Init();
106 // Should it be opened ReadOnly?
107 bool bRead(GetView()->getController().isReadOnly());
109 SetReadOnly( bRead );
111 // Insert the columns
112 OUString aColumnName( ModuleRes(STR_TAB_FIELD_COLUMN_NAME) );
113 InsertDataColumn( FIELD_NAME, aColumnName, FIELDNAME_WIDTH );
115 aColumnName = ModuleRes(STR_TAB_FIELD_COLUMN_DATATYPE);
116 InsertDataColumn( FIELD_TYPE, aColumnName, FIELDTYPE_WIDTH );
118 ::dbaccess::ODsnTypeCollection aDsnTypes(GetView()->getController().getORB());
119 bool bShowColumnDescription = aDsnTypes.supportsColumnDescription(::comphelper::getString(GetView()->getController().getDataSource()->getPropertyValue(PROPERTY_URL)));
120 aColumnName = ModuleRes(STR_TAB_HELP_TEXT);
121 InsertDataColumn( HELP_TEXT, aColumnName, bShowColumnDescription ? FIELDTYPE_WIDTH : FIELDDESCR_WIDTH );
123 if ( bShowColumnDescription )
125 aColumnName = ModuleRes(STR_COLUMN_DESCRIPTION);
126 InsertDataColumn( COLUMN_DESCRIPTION, aColumnName, FIELDTYPE_WIDTH );
129 InitCellController();
131 // Insert the rows
132 RowInserted(0, m_pRowList->size(), true);
135 OTableEditorCtrl::OTableEditorCtrl(vcl::Window* pWindow)
136 :OTableRowView(pWindow)
137 ,pNameCell(NULL)
138 ,pTypeCell(NULL)
139 ,pHelpTextCell(NULL)
140 ,pDescrCell(NULL)
141 ,pDescrWin(NULL)
142 ,nCutEvent(0)
143 ,nPasteEvent(0)
144 ,nDeleteEvent(0)
145 ,nInsNewRowsEvent(0)
146 ,nInvalidateTypeEvent(0)
147 ,m_eChildFocus(NONE)
148 ,nOldDataPos(-1)
149 ,bSaveOnMove(true)
150 ,bReadOnly(true)
151 ,m_aInvalidate(500,this)
154 SetHelpId(HID_TABDESIGN_BACKGROUND);
155 GetDataWindow().SetHelpId(HID_CTL_TABLEEDIT);
157 m_pRowList = &GetView()->getController().getRows();
158 m_nDataPos = 0;
161 SfxUndoManager& OTableEditorCtrl::GetUndoManager() const
163 return GetView()->getController().GetUndoManager();
167 void OTableEditorCtrl::SetReadOnly( bool bRead )
169 // nothing to do?
170 if (bRead == IsReadOnly())
171 // This check is important, as the underlying Def may be unnecessarily locked or unlocked
172 // or worse, this action may not be reversed afterwards
173 return;
175 bReadOnly = bRead;
177 // Disable active cells
178 long nRow(GetCurRow());
179 sal_uInt16 nCol(GetCurColumnId());
180 DeactivateCell();
182 // Select the correct Browsers cursor
183 BrowserMode nMode(BrowserMode::COLUMNSELECTION | BrowserMode::MULTISELECTION | BrowserMode::KEEPHIGHLIGHT |
184 BrowserMode::HLINES | BrowserMode::VLINES|BrowserMode::AUTOSIZE_LASTCOL);
185 if( !bReadOnly )
186 nMode |= BrowserMode::HIDECURSOR;
187 SetMode(nMode);
189 if( !bReadOnly )
190 ActivateCell( nRow, nCol );
193 void OTableEditorCtrl::InitCellController()
195 // Cell Field name
196 sal_Int32 nMaxTextLen = EDIT_NOLIMIT;
197 OUString sExtraNameChars;
198 Reference<XConnection> xCon;
201 xCon = GetView()->getController().getConnection();
202 Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
204 nMaxTextLen = xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0;
206 if( nMaxTextLen == 0 )
207 nMaxTextLen = EDIT_NOLIMIT;
208 sExtraNameChars = xMetaData.is() ? xMetaData->getExtraNameCharacters() : OUString();
211 catch(SQLException&)
213 OSL_FAIL("getMaxColumnNameLength");
216 pNameCell = VclPtr<OSQLNameEdit>::Create(&GetDataWindow(), WB_LEFT, sExtraNameChars);
217 pNameCell->SetMaxTextLen( nMaxTextLen );
218 pNameCell->setCheck( isSQL92CheckEnabled(xCon) );
220 // Cell type
221 pTypeCell = VclPtr<ListBoxControl>::Create( &GetDataWindow() );
222 pTypeCell->SetDropDownLineCount( 15 );
224 // Cell description
225 pDescrCell = VclPtr<Edit>::Create( &GetDataWindow(), WB_LEFT );
226 pDescrCell->SetMaxTextLen( MAX_DESCR_LEN );
228 pHelpTextCell = VclPtr<Edit>::Create( &GetDataWindow(), WB_LEFT );
229 pHelpTextCell->SetMaxTextLen( MAX_DESCR_LEN );
231 pNameCell->SetHelpId(HID_TABDESIGN_NAMECELL);
232 pTypeCell->SetHelpId(HID_TABDESIGN_TYPECELL);
233 pDescrCell->SetHelpId(HID_TABDESIGN_COMMENTCELL);
234 pHelpTextCell->SetHelpId(HID_TABDESIGN_HELPTEXT);
236 Size aHeight;
237 const Control* pControls[] = { pTypeCell,pDescrCell,pNameCell,pHelpTextCell};
238 for(sal_Size i= 0; i < sizeof(pControls) / sizeof(pControls[0]);++i)
240 const Size aTemp(pControls[i]->GetOptimalSize());
241 if ( aTemp.Height() > aHeight.Height() )
242 aHeight.Height() = aTemp.Height();
244 SetDataRowHeight(aHeight.Height());
246 ClearModified();
249 void OTableEditorCtrl::ClearModified()
251 pNameCell->ClearModifyFlag();
252 pDescrCell->ClearModifyFlag();
253 pHelpTextCell->ClearModifyFlag();
254 pTypeCell->SaveValue();
257 OTableEditorCtrl::~OTableEditorCtrl()
259 disposeOnce();
262 void OTableEditorCtrl::dispose()
264 // Reset the Undo-Manager
265 GetUndoManager().Clear();
267 m_aInvalidate.Stop();
269 // Take possible Events from the queue
270 if( nCutEvent )
271 Application::RemoveUserEvent( nCutEvent );
272 if( nPasteEvent )
273 Application::RemoveUserEvent( nPasteEvent );
274 if( nDeleteEvent )
275 Application::RemoveUserEvent( nDeleteEvent );
276 if( nInsNewRowsEvent )
277 Application::RemoveUserEvent( nInsNewRowsEvent );
278 if( nInvalidateTypeEvent )
279 Application::RemoveUserEvent( nInvalidateTypeEvent );
281 // Delete the control types
282 pNameCell.disposeAndClear();
283 pTypeCell.disposeAndClear();
284 pDescrCell.disposeAndClear();
285 pHelpTextCell.disposeAndClear();
286 pDescrWin.clear();
287 OTableRowView::dispose();
290 bool OTableEditorCtrl::SetDataPtr( long nRow )
292 if(nRow == -1)
293 return false;
295 OSL_ENSURE(nRow < (long)m_pRowList->size(),"Row is greater than size!");
296 if(nRow >= (long)m_pRowList->size())
297 return false;
298 pActRow = (*m_pRowList)[nRow];
299 return pActRow != 0;
302 bool OTableEditorCtrl::SeekRow(long _nRow)
304 // Call the Base class to remember which row must be repainted
305 EditBrowseBox::SeekRow(_nRow);
307 m_nCurrentPos = _nRow;
308 return SetDataPtr(_nRow);
311 void OTableEditorCtrl::PaintCell(OutputDevice& rDev, const Rectangle& rRect,
312 sal_uInt16 nColumnId ) const
314 const OUString aText( GetCellText( m_nCurrentPos, nColumnId ));
316 rDev.Push( PushFlags::CLIPREGION );
317 rDev.SetClipRegion(vcl::Region(rRect));
318 rDev.DrawText( rRect, aText, DrawTextFlags::Left | DrawTextFlags::VCenter );
319 rDev.Pop();
322 CellController* OTableEditorCtrl::GetController(long nRow, sal_uInt16 nColumnId)
324 // If EditorCtrl is ReadOnly, editing is forbidden
325 Reference<XPropertySet> xTable = GetView()->getController().getTable();
326 if (IsReadOnly() || ( xTable.is() &&
327 xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE) &&
328 ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW"))
329 return NULL;
331 // If the row is ReadOnly, editing is forbidden
332 SetDataPtr( nRow );
333 if( pActRow->IsReadOnly() )
334 return NULL;
336 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
337 switch (nColumnId)
339 case FIELD_NAME:
340 return new EditCellController( pNameCell );
341 case FIELD_TYPE:
342 if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
343 return new ListBoxCellController( pTypeCell );
344 else return NULL;
345 case HELP_TEXT:
346 if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
347 return new EditCellController( pHelpTextCell );
348 else
349 return NULL;
350 case COLUMN_DESCRIPTION:
351 if (pActFieldDescr && !pActFieldDescr->GetName().isEmpty())
352 return new EditCellController( pDescrCell );
353 else
354 return NULL;
355 default:
356 return NULL;
360 void OTableEditorCtrl::InitController(CellControllerRef&, long nRow, sal_uInt16 nColumnId)
362 SeekRow( nRow == -1 ? GetCurRow() : nRow);
363 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
364 OUString aInitString;
366 switch (nColumnId)
368 case FIELD_NAME:
369 if( pActFieldDescr )
370 aInitString = pActFieldDescr->GetName();
371 pNameCell->SetText( aInitString );
372 pNameCell->SaveValue();
373 break;
374 case FIELD_TYPE:
376 if ( pActFieldDescr && pActFieldDescr->getTypeInfo() )
377 aInitString = pActFieldDescr->getTypeInfo()->aUIName;
379 // Set the ComboBox contents
380 pTypeCell->Clear();
381 if( !pActFieldDescr )
382 break;
384 const OTypeInfoMap& rTypeInfo = GetView()->getController().getTypeInfo();
385 OTypeInfoMap::const_iterator aIter = rTypeInfo.begin();
386 OTypeInfoMap::const_iterator aEnd = rTypeInfo.end();
387 for(;aIter != aEnd;++aIter)
388 pTypeCell->InsertEntry( aIter->second->aUIName );
389 pTypeCell->SelectEntry( aInitString );
392 break;
393 case HELP_TEXT:
394 if( pActFieldDescr )
395 aInitString = pActFieldDescr->GetHelpText();
396 pHelpTextCell->SetText( aInitString );
397 pHelpTextCell->SaveValue();
398 break;
399 case COLUMN_DESCRIPTION:
400 if( pActFieldDescr )
401 aInitString = pActFieldDescr->GetDescription();
402 pDescrCell->SetText( aInitString );
403 pDescrCell->SaveValue();
404 break;
409 EditBrowseBox::RowStatus OTableEditorCtrl::GetRowStatus(long nRow) const
411 const_cast<OTableEditorCtrl*>(this)->SetDataPtr( nRow );
412 if( !pActRow )
413 return EditBrowseBox::CLEAN;
414 if (nRow >= 0 && nRow == m_nDataPos)
416 if( pActRow->IsPrimaryKey() )
417 return EditBrowseBox::CURRENT_PRIMARYKEY;
418 return EditBrowseBox::CURRENT;
420 else
422 if( pActRow->IsPrimaryKey() )
423 return EditBrowseBox::PRIMARYKEY;
424 return EditBrowseBox::CLEAN;
428 bool OTableEditorCtrl::SaveCurRow()
430 if (GetFieldDescr(GetCurRow()) == NULL)
431 // there is no data in the current row
432 return true;
433 if (!SaveModified())
434 return false;
436 SetDataPtr(GetCurRow());
437 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
438 return true;
441 void OTableEditorCtrl::DisplayData(long nRow, bool bGrabFocus)
443 // go to the correct cell
444 SetDataPtr(nRow);
446 // Disable Edit-Mode temporarily
447 bool bWasEditing = IsEditing();
448 if (bWasEditing)
449 DeactivateCell();
451 CellControllerRef aTemp;
452 InitController(aTemp, nRow, FIELD_NAME);
453 InitController(aTemp, nRow, FIELD_TYPE);
454 InitController(aTemp, nRow, COLUMN_DESCRIPTION);
455 InitController(aTemp, nRow, HELP_TEXT);
457 GoToRow(nRow);
458 // Update the Description-Window
459 GetView()->GetDescWin()->DisplayData(GetFieldDescr(nRow));
460 // redraw the row
461 RowModified(nRow);
463 // and re-enable edit mode
464 if (bWasEditing || bGrabFocus)
465 ActivateCell(nRow, GetCurColumnId(), bGrabFocus);
468 void OTableEditorCtrl::CursorMoved()
470 // New line?
471 m_nDataPos = GetCurRow();
472 if( m_nDataPos != nOldDataPos && m_nDataPos != -1)
474 CellControllerRef aTemp;
475 InitController(aTemp,m_nDataPos,FIELD_NAME);
476 InitController(aTemp,m_nDataPos,FIELD_TYPE);
477 InitController(aTemp,m_nDataPos,COLUMN_DESCRIPTION);
478 InitController(aTemp,m_nDataPos,HELP_TEXT);
481 OTableRowView::CursorMoved();
484 sal_Int32 OTableEditorCtrl::HasFieldName( const OUString& rFieldName )
487 Reference<XConnection> xCon = GetView()->getController().getConnection();
488 Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
490 ::comphelper::UStringMixEqual bCase(!xMetaData.is() || xMetaData->supportsMixedCaseQuotedIdentifiers());
492 ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aIter = m_pRowList->begin();
493 ::std::vector< ::boost::shared_ptr<OTableRow> >::iterator aEnd = m_pRowList->end();
494 sal_Int32 nCount(0);
495 for(;aIter != aEnd;++aIter)
497 OFieldDescription* pFieldDescr = (*aIter)->GetActFieldDescr();
498 if( pFieldDescr && bCase(rFieldName,pFieldDescr->GetName()))
499 nCount++;
501 return nCount;
504 bool OTableEditorCtrl::SaveData(long nRow, sal_uInt16 nColId)
506 // Store the cell content
507 SetDataPtr( nRow == -1 ? GetCurRow() : nRow);
508 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
510 switch( nColId)
512 // Store NameCell
513 case FIELD_NAME:
515 // If there is no name, do nothing
516 OUString aName(pNameCell->GetText());
518 if( aName.isEmpty() )
520 // If FieldDescr exists, the field is deleted and the old content restored
521 if (pActFieldDescr)
523 GetUndoManager().AddUndoAction(new OTableEditorTypeSelUndoAct(this, nRow, FIELD_TYPE, pActFieldDescr->getTypeInfo()));
524 SwitchType(TOTypeInfoSP());
525 pActFieldDescr = pActRow->GetActFieldDescr();
527 else
528 return true;
530 if(pActFieldDescr)
531 pActFieldDescr->SetName( aName );
532 pNameCell->ClearModifyFlag();
534 break;
537 // Store the field type
538 case FIELD_TYPE:
539 break;
541 // Store DescrCell
542 case HELP_TEXT:
544 // if the current field description is NULL, set Default
545 if( !pActFieldDescr )
547 pHelpTextCell->SetText(OUString());
548 pHelpTextCell->ClearModifyFlag();
550 else
551 pActFieldDescr->SetHelpText( pHelpTextCell->GetText() );
552 break;
554 case COLUMN_DESCRIPTION:
556 // Set the default if the field description is null
557 if( !pActFieldDescr )
559 pDescrCell->SetText(OUString());
560 pDescrCell->ClearModifyFlag();
562 else
563 pActFieldDescr->SetDescription( pDescrCell->GetText() );
564 break;
566 case FIELD_PROPERTY_DEFAULT:
567 case FIELD_PROPERTY_REQUIRED:
568 case FIELD_PROPERTY_TEXTLEN:
569 case FIELD_PROPERTY_NUMTYPE:
570 case FIELD_PROPERTY_AUTOINC:
571 case FIELD_PROPERTY_LENGTH:
572 case FIELD_PROPERTY_SCALE:
573 case FIELD_PROPERTY_BOOL_DEFAULT:
574 pDescrWin->SaveData(pActFieldDescr);
576 if ( FIELD_PROPERTY_AUTOINC == nColId && pActFieldDescr->IsAutoIncrement() )
578 OTableController& rController = GetView()->getController();
579 if ( rController.isAutoIncrementPrimaryKey() )
581 pActFieldDescr->SetPrimaryKey( true );
582 InvalidateHandleColumn();
583 Invalidate();
586 break;
588 return true;
591 bool OTableEditorCtrl::SaveModified()
593 sal_uInt16 nColId = GetCurColumnId();
595 switch( nColId )
597 // Fieled type
598 case FIELD_TYPE:
600 // Reset the type
601 resetType();
602 } break;
605 return true;
608 bool OTableEditorCtrl::CursorMoving(long nNewRow, sal_uInt16 nNewCol)
611 if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol))
612 return false;
614 // Called after SaveModified(), current row is still the old one
615 m_nDataPos = nNewRow;
616 nOldDataPos = GetCurRow();
618 // Reset the markers
619 InvalidateStatusCell( nOldDataPos );
620 InvalidateStatusCell( m_nDataPos );
622 // Store the data from the Property window
623 if( SetDataPtr(nOldDataPos) && pDescrWin)
624 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
626 // Show new data in the Property window
627 if( SetDataPtr(m_nDataPos) && pDescrWin)
628 pDescrWin->DisplayData( pActRow->GetActFieldDescr() );
630 return true;
633 IMPL_LINK_NOARG( OTableEditorCtrl, InvalidateFieldType )
635 nInvalidateTypeEvent = 0;
636 Invalidate( GetFieldRectPixel(nOldDataPos, FIELD_TYPE) );
638 return 0;
641 void OTableEditorCtrl::CellModified( long nRow, sal_uInt16 nColId )
644 // If the description is null, use the default
645 if(nRow == -1)
646 nRow = GetCurRow();
647 SetDataPtr( nRow );
648 OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr();
650 OUString sActionDescription;
651 switch ( nColId )
653 case FIELD_NAME: sActionDescription = ModuleRes( STR_CHANGE_COLUMN_NAME ); break;
654 case FIELD_TYPE: sActionDescription = ModuleRes( STR_CHANGE_COLUMN_TYPE ); break;
655 case HELP_TEXT:
656 case COLUMN_DESCRIPTION: sActionDescription = ModuleRes( STR_CHANGE_COLUMN_DESCRIPTION ); break;
657 default: sActionDescription = ModuleRes( STR_CHANGE_COLUMN_ATTRIBUTE ); break;
660 GetUndoManager().EnterListAction( sActionDescription, OUString() );
661 if (!pActFieldDescr)
663 const OTypeInfoMap& rTypeInfoMap = GetView()->getController().getTypeInfo();
664 if ( !rTypeInfoMap.empty() )
666 OTypeInfoMap::const_iterator aTypeIter = rTypeInfoMap.find(DataType::VARCHAR);
667 if ( aTypeIter == rTypeInfoMap.end() )
668 aTypeIter = rTypeInfoMap.begin();
669 pActRow->SetFieldType( aTypeIter->second );
671 else
672 pActRow->SetFieldType( GetView()->getController().getTypeInfoFallBack() );
674 nInvalidateTypeEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, InvalidateFieldType), NULL, true );
675 pActFieldDescr = pActRow->GetActFieldDescr();
676 pDescrWin->DisplayData( pActFieldDescr );
677 GetUndoManager().AddUndoAction( new OTableEditorTypeSelUndoAct(this, nRow, nColId+1, TOTypeInfoSP()) );
680 if( nColId != FIELD_TYPE )
681 GetUndoManager().AddUndoAction( new OTableDesignCellUndoAct(this, nRow, nColId) );
682 else
684 GetUndoManager().AddUndoAction(new OTableEditorTypeSelUndoAct(this, GetCurRow(), nColId, GetFieldDescr(GetCurRow())->getTypeInfo()));
685 resetType();
688 SaveData(nRow,nColId);
689 // SaveData could create a undo action as well
690 GetUndoManager().LeaveListAction();
691 RowModified(nRow);
692 CellControllerRef xController(Controller());
693 if(xController.Is())
694 xController->SetModified();
696 // Set the Modify flag
697 GetView()->getController().setModified( sal_True );
698 InvalidateFeatures();
701 void OTableEditorCtrl::resetType()
703 sal_Int32 nPos = pTypeCell->GetSelectEntryPos();
704 if(nPos != LISTBOX_ENTRY_NOTFOUND)
705 SwitchType( GetView()->getController().getTypeInfo(nPos) );
706 else
707 SwitchType(TOTypeInfoSP());
710 void OTableEditorCtrl::CellModified()
712 CellModified( GetCurRow(), GetCurColumnId() );
715 void OTableEditorCtrl::InvalidateFeatures()
717 GetView()->getController().InvalidateFeature(SID_UNDO);
718 GetView()->getController().InvalidateFeature(SID_REDO);
719 GetView()->getController().InvalidateFeature(SID_SAVEDOC);
722 void OTableEditorCtrl::CopyRows()
724 // set to the right row and save it
725 if( SetDataPtr(m_nDataPos) )
726 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
728 // Copy selected rows to the ClipboardList
729 ::boost::shared_ptr<OTableRow> pClipboardRow;
730 ::boost::shared_ptr<OTableRow> pRow;
731 ::std::vector< ::boost::shared_ptr<OTableRow> > vClipboardList;
732 vClipboardList.reserve(GetSelectRowCount());
734 for( long nIndex=FirstSelectedRow(); nIndex >= 0 && nIndex < static_cast<long>(m_pRowList->size()); nIndex=NextSelectedRow() )
736 pRow = (*m_pRowList)[nIndex];
737 OSL_ENSURE(pRow,"OTableEditorCtrl::CopyRows: Row is NULL!");
738 if ( pRow && pRow->GetActFieldDescr() )
740 pClipboardRow.reset(new OTableRow( *pRow ));
741 vClipboardList.push_back( pClipboardRow);
744 if(!vClipboardList.empty())
746 OTableRowExchange* pData = new OTableRowExchange(vClipboardList);
747 Reference< ::com::sun::star::datatransfer::XTransferable> xRef = pData;
748 pData->CopyToClipboard(GetParent());
752 OUString OTableEditorCtrl::GenerateName( const OUString& rName )
754 // Create a base name for appending numbers to
755 OUString aBaseName;
756 Reference<XConnection> xCon = GetView()->getController().getConnection();
757 Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>();
759 sal_Int32 nMaxTextLen(xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0);
761 if( (rName.getLength()+2) >nMaxTextLen )
762 aBaseName = rName.copy( 0, nMaxTextLen-2 );
763 else
764 aBaseName = rName;
766 // append a sequential number to the base name (up to 99)
767 OUString aFieldName( rName);
768 sal_Int32 i=1;
769 while( HasFieldName(aFieldName) )
771 aFieldName = aBaseName + OUString::number(i);
772 i++;
775 return aFieldName;
778 void OTableEditorCtrl::InsertRows( long nRow )
781 ::std::vector< ::boost::shared_ptr<OTableRow> > vInsertedUndoRedoRows; // need for undo/redo handling
782 // get rows from clipboard
783 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
784 if(aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED))
786 ::tools::SvRef<SotStorageStream> aStreamRef;
787 bool bOk = aTransferData.GetSotStorageStream(SotClipboardFormatId::SBA_TABED,aStreamRef);
788 if (bOk && aStreamRef.Is())
790 aStreamRef->Seek(STREAM_SEEK_TO_BEGIN);
791 aStreamRef->ResetError();
792 long nInsertRow = nRow;
793 OUString aFieldName;
794 ::boost::shared_ptr<OTableRow> pRow;
795 sal_Int32 nSize = 0;
796 (*aStreamRef).ReadInt32( nSize );
797 vInsertedUndoRedoRows.reserve(nSize);
798 for(sal_Int32 i=0;i < nSize;++i)
800 pRow.reset(new OTableRow());
801 ReadOTableRow( *aStreamRef, *pRow );
802 pRow->SetReadOnly( false );
803 sal_Int32 nType = pRow->GetActFieldDescr()->GetType();
804 if ( pRow->GetActFieldDescr() )
805 pRow->GetActFieldDescr()->SetType(GetView()->getController().getTypeInfoByType(nType));
806 // Adjust the field names
807 aFieldName = GenerateName( pRow->GetActFieldDescr()->GetName() );
808 pRow->GetActFieldDescr()->SetName( aFieldName );
809 pRow->SetPos(nInsertRow);
810 m_pRowList->insert( m_pRowList->begin()+nInsertRow,pRow );
811 vInsertedUndoRedoRows.push_back(::boost::shared_ptr<OTableRow>(new OTableRow(*pRow)));
812 nInsertRow++;
816 // RowInserted calls CursorMoved.
817 // The UI data should not be stored here.
818 bSaveOnMove = false;
819 RowInserted( nRow,vInsertedUndoRedoRows.size(), true );
820 bSaveOnMove = true;
822 // Create the Undo-Action
823 GetUndoManager().AddUndoAction( new OTableEditorInsUndoAct(this, nRow,vInsertedUndoRedoRows) );
824 GetView()->getController().setModified( sal_True );
825 InvalidateFeatures();
828 void OTableEditorCtrl::DeleteRows()
830 OSL_ENSURE(GetView()->getController().isDropAllowed(),"Call of DeleteRows not valid here. Please check isDropAllowed!");
831 // Create the Undo-Action
832 GetUndoManager().AddUndoAction( new OTableEditorDelUndoAct(this) );
834 // Delete all marked rows
835 long nIndex = FirstSelectedRow();
836 nOldDataPos = nIndex;
837 bSaveOnMove = false;
839 while( nIndex >= 0 && nIndex < static_cast<long>(m_pRowList->size()) )
841 // Remove rows
842 m_pRowList->erase( m_pRowList->begin()+nIndex );
843 RowRemoved( nIndex, 1, true );
845 // Insert the empty row at the end
846 m_pRowList->push_back( ::boost::shared_ptr<OTableRow>(new OTableRow()));
847 RowInserted( GetRowCount()-1, 1, true );
849 nIndex = FirstSelectedRow();
852 bSaveOnMove = true;
854 // Force the current record to be displayed
855 m_nDataPos = GetCurRow();
856 InvalidateStatusCell( nOldDataPos );
857 InvalidateStatusCell( m_nDataPos );
858 SetDataPtr( m_nDataPos );
859 ActivateCell();
860 pDescrWin->DisplayData( pActRow->GetActFieldDescr() );
861 GetView()->getController().setModified( sal_True );
862 InvalidateFeatures();
865 void OTableEditorCtrl::InsertNewRows( long nRow )
867 OSL_ENSURE(GetView()->getController().isAddAllowed(),"Call of InsertNewRows not valid here. Please check isAppendAllowed!");
868 // Create Undo-Action
869 long nInsertRows = GetSelectRowCount();
870 if( !nInsertRows )
871 nInsertRows = 1;
872 GetUndoManager().AddUndoAction( new OTableEditorInsNewUndoAct(this, nRow, nInsertRows) );
873 // Insert the number of selected rows
874 for( long i=nRow; i<(nRow+nInsertRows); i++ )
875 m_pRowList->insert( m_pRowList->begin()+i ,::boost::shared_ptr<OTableRow>(new OTableRow()));
876 RowInserted( nRow, nInsertRows, true );
878 GetView()->getController().setModified( sal_True );
879 InvalidateFeatures();
882 OUString OTableEditorCtrl::GetControlText( long nRow, sal_uInt16 nColId )
884 // Read the Browser Controls
885 if( nColId < FIELD_FIRST_VIRTUAL_COLUMN )
887 GoToRow( nRow );
888 GoToColumnId( nColId );
889 CellControllerRef xController = Controller();
890 if(xController.Is())
891 return xController->GetWindow().GetText();
892 else
893 return GetCellText(nRow,nColId);
896 // Read the Controls on the Tabpage
897 else
898 return pDescrWin->GetControlText( nColId );
901 void OTableEditorCtrl::SetControlText( long nRow, sal_uInt16 nColId, const OUString& rText )
903 // Set the Browser Controls
904 if( nColId < FIELD_FIRST_VIRTUAL_COLUMN )
906 GoToRow( nRow );
907 GoToColumnId( nColId );
908 CellControllerRef xController = Controller();
909 if(xController.Is())
910 xController->GetWindow().SetText( rText );
911 else
912 RowModified(nRow,nColId);
915 // Set the Tabpage controls
916 else
918 pDescrWin->SetControlText( nColId, rText );
922 void OTableEditorCtrl::SetCellData( long nRow, sal_uInt16 nColId, const TOTypeInfoSP& _pTypeInfo )
924 // Relocate the current pointer
925 if( nRow == -1 )
926 nRow = GetCurRow();
927 OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
928 if( !pFieldDescr && nColId != FIELD_TYPE)
929 return;
931 // Set individual fields
932 switch( nColId )
934 case FIELD_TYPE:
935 SwitchType( _pTypeInfo );
936 break;
937 default:
938 OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!");
940 SetControlText(nRow,nColId,_pTypeInfo.get() ? _pTypeInfo->aUIName : OUString());
943 void OTableEditorCtrl::SetCellData( long nRow, sal_uInt16 nColId, const ::com::sun::star::uno::Any& _rNewData )
945 // Relocate the current pointer
946 if( nRow == -1 )
947 nRow = GetCurRow();
948 OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
949 if( !pFieldDescr && nColId != FIELD_TYPE)
950 return;
952 OUString sValue;
953 // Set indvidual fields
954 switch( nColId )
956 case FIELD_NAME:
957 sValue = ::comphelper::getString(_rNewData);
958 pFieldDescr->SetName( sValue );
959 break;
961 case FIELD_TYPE:
962 OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!");
963 break;
965 case COLUMN_DESCRIPTION:
966 pFieldDescr->SetDescription( sValue = ::comphelper::getString(_rNewData) );
967 break;
969 case FIELD_PROPERTY_DEFAULT:
970 pFieldDescr->SetControlDefault( _rNewData );
971 sValue = GetView()->GetDescWin()->getGenPage()->getFieldControl()->getControlDefault(pFieldDescr);
972 break;
974 case FIELD_PROPERTY_REQUIRED:
976 sValue = ::comphelper::getString(_rNewData);
977 pFieldDescr->SetIsNullable( sValue.toInt32() );
979 break;
981 case FIELD_PROPERTY_TEXTLEN:
982 case FIELD_PROPERTY_LENGTH:
984 sValue = ::comphelper::getString(_rNewData);
985 pFieldDescr->SetPrecision( sValue.toInt32() );
987 break;
989 case FIELD_PROPERTY_NUMTYPE:
990 OSL_FAIL("OTableEditorCtrl::SetCellData: invalid column!");
991 break;
993 case FIELD_PROPERTY_AUTOINC:
995 OUString strYes(ModuleRes(STR_VALUE_YES));
996 sValue = ::comphelper::getString(_rNewData);
997 pFieldDescr->SetAutoIncrement(sValue == strYes);
999 break;
1000 case FIELD_PROPERTY_SCALE:
1002 sValue = ::comphelper::getString(_rNewData);
1003 pFieldDescr->SetScale(sValue.toInt32());
1005 break;
1007 case FIELD_PROPERTY_BOOL_DEFAULT:
1008 sValue = GetView()->GetDescWin()->BoolStringPersistent(::comphelper::getString(_rNewData));
1009 pFieldDescr->SetControlDefault(makeAny(OUString(sValue)));
1010 break;
1012 case FIELD_PROPERTY_FORMAT:
1014 sValue = ::comphelper::getString(_rNewData);
1015 pFieldDescr->SetFormatKey(sValue.toInt32());
1017 break;
1020 SetControlText(nRow,nColId,sValue);
1023 Any OTableEditorCtrl::GetCellData( long nRow, sal_uInt16 nColId )
1025 OFieldDescription* pFieldDescr = GetFieldDescr( nRow );
1026 if( !pFieldDescr )
1027 return Any();
1029 // Relocate the current pointer
1030 if( nRow==-1 )
1031 nRow = GetCurRow();
1032 SetDataPtr( nRow );
1034 static const OUString strYes(ModuleRes(STR_VALUE_YES));
1035 static const OUString strNo(ModuleRes(STR_VALUE_NO));
1036 OUString sValue;
1037 // Read out the fields
1038 switch( nColId )
1040 case FIELD_NAME:
1041 sValue = pFieldDescr->GetName();
1042 break;
1044 case FIELD_TYPE:
1045 if ( pFieldDescr->getTypeInfo() )
1046 sValue = pFieldDescr->getTypeInfo()->aUIName;
1047 break;
1049 case COLUMN_DESCRIPTION:
1050 sValue = pFieldDescr->GetDescription();
1051 break;
1052 case HELP_TEXT:
1053 sValue = pFieldDescr->GetHelpText();
1054 break;
1056 case FIELD_PROPERTY_DEFAULT:
1057 return pFieldDescr->GetControlDefault();
1059 case FIELD_PROPERTY_REQUIRED:
1060 sValue = pFieldDescr->GetIsNullable() == ColumnValue::NULLABLE ? strYes : strNo;
1061 break;
1063 case FIELD_PROPERTY_TEXTLEN:
1064 case FIELD_PROPERTY_LENGTH:
1065 sValue = OUString::number(pFieldDescr->GetPrecision());
1066 break;
1068 case FIELD_PROPERTY_NUMTYPE:
1069 OSL_FAIL("OTableEditorCtrl::GetCellData: invalid column!");
1070 break;
1072 case FIELD_PROPERTY_AUTOINC:
1073 sValue = pFieldDescr->IsAutoIncrement() ? strYes : strNo;
1074 break;
1076 case FIELD_PROPERTY_SCALE:
1077 sValue = OUString::number(pFieldDescr->GetScale());
1078 break;
1080 case FIELD_PROPERTY_BOOL_DEFAULT:
1081 sValue = GetView()->GetDescWin()->BoolStringUI(::comphelper::getString(pFieldDescr->GetControlDefault()));
1082 break;
1084 case FIELD_PROPERTY_FORMAT:
1085 sValue = OUString::number(pFieldDescr->GetFormatKey());
1086 break;
1089 return makeAny(sValue);
1092 OUString OTableEditorCtrl::GetCellText( long nRow, sal_uInt16 nColId ) const
1094 OUString sCellText;
1095 const_cast< OTableEditorCtrl* >( this )->GetCellData( nRow, nColId ) >>= sCellText;
1096 return sCellText;
1099 sal_uInt32 OTableEditorCtrl::GetTotalCellWidth(long nRow, sal_uInt16 nColId)
1101 return GetTextWidth(GetCellText(nRow, nColId)) + 2 * GetTextWidth(OUString('0'));
1104 OFieldDescription* OTableEditorCtrl::GetFieldDescr( long nRow )
1106 std::vector< ::boost::shared_ptr<OTableRow> >::size_type nListCount(
1107 m_pRowList->size());
1108 if( (nRow<0) || (sal::static_int_cast< unsigned long >(nRow)>=nListCount) )
1110 OSL_FAIL("(nRow<0) || (nRow>=nListCount)");
1111 return NULL;
1113 ::boost::shared_ptr<OTableRow> pRow = (*m_pRowList)[ nRow ];
1114 if( !pRow )
1115 return NULL;
1116 return pRow->GetActFieldDescr();
1119 bool OTableEditorCtrl::IsCutAllowed( long nRow )
1121 bool bIsCutAllowed = (GetView()->getController().isAddAllowed() && GetView()->getController().isDropAllowed()) ||
1122 GetView()->getController().isAlterAllowed();
1124 if(bIsCutAllowed)
1126 switch(m_eChildFocus)
1128 case DESCRIPTION:
1129 bIsCutAllowed = !pDescrCell->GetSelected().isEmpty();
1130 break;
1131 case HELPTEXT:
1132 bIsCutAllowed = !pHelpTextCell->GetSelected().isEmpty();
1133 break;
1134 case NAME:
1135 bIsCutAllowed = !pNameCell->GetSelected().isEmpty();
1136 break;
1137 case ROW:
1138 bIsCutAllowed = IsCopyAllowed(nRow);
1139 break;
1140 default:
1141 bIsCutAllowed = false;
1142 break;
1146 return bIsCutAllowed;
1149 bool OTableEditorCtrl::IsCopyAllowed( long /*nRow*/ )
1151 bool bIsCopyAllowed = false;
1152 if(m_eChildFocus == DESCRIPTION )
1153 bIsCopyAllowed = !pDescrCell->GetSelected().isEmpty();
1154 else if(HELPTEXT == m_eChildFocus )
1155 bIsCopyAllowed = !pHelpTextCell->GetSelected().isEmpty();
1156 else if(m_eChildFocus == NAME)
1157 bIsCopyAllowed = !pNameCell->GetSelected().isEmpty();
1158 else if(m_eChildFocus == ROW)
1160 Reference<XPropertySet> xTable = GetView()->getController().getTable();
1161 if( !GetSelectRowCount() || (xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW"))
1162 return false;
1164 // If one of the selected rows is empty, Copy is not possible
1165 ::boost::shared_ptr<OTableRow> pRow;
1166 long nIndex = FirstSelectedRow();
1167 while( nIndex >= 0 && nIndex < static_cast<long>(m_pRowList->size()) )
1169 pRow = (*m_pRowList)[nIndex];
1170 if( !pRow->GetActFieldDescr() )
1171 return false;
1173 nIndex = NextSelectedRow();
1176 bIsCopyAllowed = true;
1179 return bIsCopyAllowed;
1182 bool OTableEditorCtrl::IsPasteAllowed( long /*nRow*/ )
1184 bool bAllowed = GetView()->getController().isAddAllowed();
1185 if ( bAllowed )
1187 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
1188 bool bRowFormat = aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED);
1189 if ( m_eChildFocus == ROW )
1190 bAllowed = bRowFormat;
1191 else
1192 bAllowed = !bRowFormat && aTransferData.HasFormat(SotClipboardFormatId::STRING);
1195 return bAllowed;
1198 void OTableEditorCtrl::cut()
1200 if(m_eChildFocus == NAME)
1202 if(GetView()->getController().isAlterAllowed())
1204 SaveData(-1,FIELD_NAME);
1205 pNameCell->Cut();
1206 CellModified(-1,FIELD_NAME);
1209 else if(m_eChildFocus == DESCRIPTION)
1211 if(GetView()->getController().isAlterAllowed())
1213 SaveData(-1,COLUMN_DESCRIPTION);
1214 pDescrCell->Cut();
1215 CellModified(-1,COLUMN_DESCRIPTION);
1218 else if(HELPTEXT == m_eChildFocus )
1220 if(GetView()->getController().isAlterAllowed())
1222 SaveData(-1,HELP_TEXT);
1223 pHelpTextCell->Cut();
1224 CellModified(-1,HELP_TEXT);
1227 else if(m_eChildFocus == ROW)
1229 if (nCutEvent)
1230 Application::RemoveUserEvent(nCutEvent);
1231 nCutEvent = Application::PostUserEvent(LINK(this, OTableEditorCtrl, DelayedCut), NULL, true);
1235 void OTableEditorCtrl::copy()
1237 if(GetSelectRowCount())
1238 OTableRowView::copy();
1239 else if(m_eChildFocus == NAME)
1240 pNameCell->Copy();
1241 else if(HELPTEXT == m_eChildFocus )
1242 pHelpTextCell->Copy();
1243 else if(m_eChildFocus == DESCRIPTION )
1244 pDescrCell->Copy();
1247 void OTableEditorCtrl::paste()
1249 TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent()));
1250 if(aTransferData.HasFormat(SotClipboardFormatId::SBA_TABED))
1252 if( nPasteEvent )
1253 Application::RemoveUserEvent( nPasteEvent );
1254 nPasteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedPaste), NULL, true );
1256 else if(m_eChildFocus == NAME)
1258 if(GetView()->getController().isAlterAllowed())
1260 pNameCell->Paste();
1261 CellModified();
1264 else if(HELPTEXT == m_eChildFocus )
1266 if(GetView()->getController().isAlterAllowed())
1268 pHelpTextCell->Paste();
1269 CellModified();
1272 else if(m_eChildFocus == DESCRIPTION)
1274 if(GetView()->getController().isAlterAllowed())
1276 pDescrCell->Paste();
1277 CellModified();
1282 bool OTableEditorCtrl::IsDeleteAllowed( long /*nRow*/ )
1285 return GetSelectRowCount() != 0 && GetView()->getController().isDropAllowed();
1288 bool OTableEditorCtrl::IsInsertNewAllowed( long nRow )
1291 bool bInsertNewAllowed = GetView()->getController().isAddAllowed();
1292 // If fields can be added, Paste in the new fields
1293 if (bInsertNewAllowed && !GetView()->getController().isDropAllowed())
1295 SetDataPtr(nRow);
1296 if( GetActRow()->IsReadOnly() )
1297 return false;
1300 return bInsertNewAllowed;
1303 bool OTableEditorCtrl::IsPrimaryKeyAllowed( long /*nRow*/ )
1305 if( !GetSelectRowCount() )
1306 return false;
1308 OTableController& rController = GetView()->getController();
1309 if ( !rController.getSdbMetaData().supportsPrimaryKeys() )
1310 return false;
1312 Reference<XPropertySet> xTable = rController.getTable();
1313 // Key must not be changed
1314 // This applies only if the table is not new and not a ::com::sun::star::sdbcx::View. Otherwise no DROP is executed
1316 if(xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == "VIEW")
1317 return false;
1318 // If there is an empty field, no primary key
1319 // The entry is only permitted if
1320 // - there are no empty entries in the selection
1321 // - No Memo or Image entries
1322 // - DROP is not permitted (see above) and the column is not Required (not null flag is not set).
1323 long nIndex = FirstSelectedRow();
1324 ::boost::shared_ptr<OTableRow> pRow;
1325 while( nIndex >= 0 && nIndex < static_cast<long>(m_pRowList->size()) )
1327 pRow = (*m_pRowList)[nIndex];
1328 OFieldDescription* pFieldDescr = pRow->GetActFieldDescr();
1329 if(!pFieldDescr)
1330 return false;
1331 else
1333 // Memo and Image fields cannot be primary keys
1334 // or if the column cannot be dropped and the Required flag is not set
1335 // or if a ::com::sun::star::sdbcx::View is available and the Required flag is not set
1336 TOTypeInfoSP pTypeInfo = pFieldDescr->getTypeInfo();
1337 if( pTypeInfo->nSearchType == ColumnSearch::NONE
1338 || (pFieldDescr->IsNullable() && pRow->IsReadOnly())
1340 return false;
1343 nIndex = NextSelectedRow();
1346 return true;
1349 void OTableEditorCtrl::Command(const CommandEvent& rEvt)
1351 switch (rEvt.GetCommand())
1353 case CommandEventId::ContextMenu:
1355 Point aMenuPos( rEvt.GetMousePosPixel() );
1356 if (!rEvt.IsMouseEvent())
1358 if ( 1 == GetSelectColumnCount() )
1360 sal_uInt16 nSelId = GetColumnId(
1361 sal::static_int_cast< sal_uInt16 >(
1362 FirstSelectedColumn() ) );
1363 ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, false ) );
1365 aMenuPos = aColRect.TopCenter();
1367 else if ( GetSelectRowCount() > 0 )
1369 ::Rectangle aColRect( GetFieldRectPixel( FirstSelectedRow(), HANDLE_ID, true ) );
1371 aMenuPos = aColRect.TopCenter();
1373 else
1375 OTableRowView::Command(rEvt);
1376 return;
1380 // Show the Context menu
1381 if( !IsReadOnly() )
1383 sal_uInt16 nColId = GetColumnAtXPosPixel(aMenuPos.X());
1384 long nRow = GetRowAtYPosPixel(aMenuPos.Y());
1386 if ( HANDLE_ID != nColId )
1388 if ( nRow < 0 && nColId != BROWSER_INVALIDID )
1389 { // hit the header
1390 if ( 3 != nColId )
1391 { // 3 would mean the last column, and this last column is auto-sized
1392 if ( !IsColumnSelected( nColId ) )
1393 SelectColumnId( nColId );
1395 PopupMenu aContextMenu( ModuleRes( RID_QUERYCOLPOPUPMENU ) );
1396 aContextMenu.EnableItem( SID_DELETE, false );
1397 aContextMenu.RemoveDisabledEntries(true, true);
1398 switch ( aContextMenu.Execute( this, aMenuPos ) )
1400 case ID_BROWSER_COLWIDTH:
1401 adjustBrowseBoxColumnWidth( this, nColId );
1402 break;
1407 else
1409 PopupMenu aContextMenu(ModuleRes(RID_TABLEDESIGNROWPOPUPMENU));
1411 aContextMenu.EnableItem( SID_CUT, IsCutAllowed(nRow) );
1412 aContextMenu.EnableItem( SID_COPY, IsCopyAllowed(nRow) );
1413 aContextMenu.EnableItem( SID_PASTE, IsPasteAllowed(nRow) );
1414 aContextMenu.EnableItem( SID_DELETE, IsDeleteAllowed(nRow) );
1415 aContextMenu.EnableItem( SID_TABLEDESIGN_TABED_PRIMARYKEY, IsPrimaryKeyAllowed(nRow) );
1416 aContextMenu.EnableItem( SID_TABLEDESIGN_INSERTROWS, IsInsertNewAllowed(nRow) );
1417 aContextMenu.CheckItem( SID_TABLEDESIGN_TABED_PRIMARYKEY, IsRowSelected(GetCurRow()) && IsPrimaryKey() );
1419 // remove all the disable entries
1420 aContextMenu.RemoveDisabledEntries(true, true);
1422 if( SetDataPtr(m_nDataPos) )
1423 pDescrWin->SaveData( pActRow->GetActFieldDescr() );
1425 // All actions which change the number of rows must be run asynchronously
1426 // otherwise there may be problems between the Context menu and the Browser
1427 m_nDataPos = GetCurRow();
1428 switch (aContextMenu.Execute(this, aMenuPos))
1430 case SID_CUT:
1431 cut();
1432 break;
1433 case SID_COPY:
1434 copy();
1435 break;
1436 case SID_PASTE:
1437 paste();
1438 break;
1439 case SID_DELETE:
1440 if( nDeleteEvent )
1441 Application::RemoveUserEvent( nDeleteEvent );
1442 nDeleteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedDelete), NULL, true );
1443 break;
1444 case SID_TABLEDESIGN_INSERTROWS:
1445 if( nInsNewRowsEvent )
1446 Application::RemoveUserEvent( nInsNewRowsEvent );
1447 nInsNewRowsEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedInsNewRows), NULL, true );
1448 break;
1449 case SID_TABLEDESIGN_TABED_PRIMARYKEY:
1450 SetPrimaryKey( !IsPrimaryKey() );
1451 break;
1452 default:
1453 break;
1458 break;
1459 default:
1460 OTableRowView::Command(rEvt);
1465 IMPL_LINK_NOARG( OTableEditorCtrl, DelayedCut )
1467 nCutEvent = 0;
1468 OTableRowView::cut();
1469 return 0;
1472 IMPL_LINK_NOARG( OTableEditorCtrl, DelayedPaste )
1474 nPasteEvent = 0;
1476 sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition();
1477 if ( !GetView()->getController().getTable().is() )
1478 nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : GetCurRow();
1480 if (!IsInsertNewAllowed(nPastePosition))
1481 { // Insertion is not allowed, only appending, so test if there are full cells after the PastePosition
1483 sal_Int32 nFreeFromPos; // from here on there are only empty rows
1484 ::std::vector< ::boost::shared_ptr<OTableRow> >::reverse_iterator aIter = m_pRowList->rbegin();
1485 for(nFreeFromPos = m_pRowList->size();
1486 aIter != m_pRowList->rend() && (!(*aIter) || !(*aIter)->GetActFieldDescr() || (*aIter)->GetActFieldDescr()->GetName().isEmpty());
1487 --nFreeFromPos, ++aIter)
1489 if (nPastePosition < nFreeFromPos) // if at least one PastePosition is full, go right to the end
1490 nPastePosition = nFreeFromPos;
1493 OTableRowView::Paste( nPastePosition );
1494 SetNoSelection();
1495 GoToRow( nPastePosition );
1497 return 0;
1500 IMPL_LINK_NOARG( OTableEditorCtrl, DelayedDelete )
1502 nDeleteEvent = 0;
1503 DeleteRows();
1504 return 0;
1507 IMPL_LINK_NOARG( OTableEditorCtrl, DelayedInsNewRows )
1509 nInsNewRowsEvent = 0;
1510 sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition();
1511 if ( !GetView()->getController().getTable().is() )
1512 nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : m_nDataPos;
1514 InsertNewRows( nPastePosition );
1515 SetNoSelection();
1516 GoToRow( nPastePosition );
1518 return 0;
1521 void OTableEditorCtrl::AdjustFieldDescription(OFieldDescription* _pFieldDesc,
1522 MultiSelection& _rMultiSel,
1523 sal_Int32 _nPos,
1524 bool _bSet,
1525 bool _bPrimaryKey)
1527 _pFieldDesc->SetPrimaryKey( _bPrimaryKey );
1528 if(!_bSet && _pFieldDesc->getTypeInfo()->bNullable)
1530 _pFieldDesc->SetIsNullable(ColumnValue::NO_NULLS);
1531 _pFieldDesc->SetControlDefault(Any());
1533 if ( _pFieldDesc->IsAutoIncrement() && !_bPrimaryKey )
1535 OTableController& rController = GetView()->getController();
1536 if ( rController.isAutoIncrementPrimaryKey() )
1538 _pFieldDesc->SetAutoIncrement(false);
1541 // update field description
1542 pDescrWin->DisplayData(_pFieldDesc);
1544 _rMultiSel.Insert( _nPos );
1545 _rMultiSel.Select( _nPos );
1548 void OTableEditorCtrl::SetPrimaryKey( bool bSet )
1550 // Delete any existing Primary Keys
1551 MultiSelection aDeletedPrimKeys;
1552 aDeletedPrimKeys.SetTotalRange( Range(0,GetRowCount()) );
1554 ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = m_pRowList->begin();
1555 ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aEnd = m_pRowList->end();
1556 for(sal_Int32 nRow = 0;aIter != aEnd;++aIter,++nRow)
1558 OFieldDescription* pFieldDescr = (*aIter)->GetActFieldDescr();
1559 if( pFieldDescr && (*aIter)->IsPrimaryKey() && (!bSet || !IsRowSelected(nRow)) )
1561 AdjustFieldDescription(pFieldDescr,aDeletedPrimKeys,nRow,bSet,false);
1565 // Set the primary keys of the marked rows
1566 MultiSelection aInsertedPrimKeys;
1567 aInsertedPrimKeys.SetTotalRange( Range(0,GetRowCount()) );
1568 if( bSet )
1570 long nIndex = FirstSelectedRow();
1571 while( nIndex >= 0 && nIndex < static_cast<long>(m_pRowList->size()) )
1573 // Set the key
1574 ::boost::shared_ptr<OTableRow> pRow = (*m_pRowList)[nIndex];
1575 OFieldDescription* pFieldDescr = pRow->GetActFieldDescr();
1576 if(pFieldDescr)
1577 AdjustFieldDescription(pFieldDescr,aInsertedPrimKeys,nIndex,false,true);
1579 nIndex = NextSelectedRow();
1583 GetUndoManager().AddUndoAction( new OPrimKeyUndoAct(this, aDeletedPrimKeys, aInsertedPrimKeys) );
1585 // Invalidate the handle-columns
1586 InvalidateHandleColumn();
1588 // Set the TableDocSh's ModifyFlag
1589 GetView()->getController().setModified( sal_True );
1590 InvalidateFeatures();
1593 bool OTableEditorCtrl::IsPrimaryKey()
1595 // Are all marked fields part of the Primary Key ?
1596 long nPrimaryKeys = 0;
1597 ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aIter = m_pRowList->begin();
1598 ::std::vector< ::boost::shared_ptr<OTableRow> >::const_iterator aEnd = m_pRowList->end();
1599 for(sal_Int32 nRow=0;aIter != aEnd;++aIter,++nRow)
1601 if( IsRowSelected(nRow) && !(*aIter)->IsPrimaryKey() )
1602 return false;
1603 if( (*aIter)->IsPrimaryKey() )
1604 ++nPrimaryKeys;
1607 // Are there any unselected fields that are part of the Key ?
1608 return GetSelectRowCount() == nPrimaryKeys;
1611 void OTableEditorCtrl::SwitchType( const TOTypeInfoSP& _pType )
1613 // if there is no assigned field name
1614 long nRow(GetCurRow());
1615 OFieldDescription* pActFieldDescr = GetFieldDescr( nRow );
1616 if( pActFieldDescr )
1617 // Store the old description
1618 pDescrWin->SaveData( pActFieldDescr );
1620 if ( nRow < 0 || nRow > static_cast<long>(m_pRowList->size()) )
1621 return;
1622 // Show the new description
1623 ::boost::shared_ptr<OTableRow> pRow = (*m_pRowList)[nRow];
1624 pRow->SetFieldType( _pType, true );
1625 if ( _pType.get() )
1627 const sal_Int32 nCurrentlySelected = pTypeCell->GetSelectEntryPos();
1629 if ( ( LISTBOX_ENTRY_NOTFOUND == nCurrentlySelected )
1630 || ( GetView()->getController().getTypeInfo( nCurrentlySelected ) != _pType )
1633 sal_Int32 nEntryPos = 0;
1634 const OTypeInfoMap& rTypeInfo = GetView()->getController().getTypeInfo();
1635 OTypeInfoMap::const_iterator aIter = rTypeInfo.begin();
1636 OTypeInfoMap::const_iterator aEnd = rTypeInfo.end();
1637 for(;aIter != aEnd;++aIter,++nEntryPos)
1639 if(aIter->second == _pType)
1640 break;
1642 if (nEntryPos < pTypeCell->GetEntryCount())
1643 pTypeCell->SelectEntryPos( nEntryPos );
1647 pActFieldDescr = pRow->GetActFieldDescr();
1648 if (pActFieldDescr != NULL && !pActFieldDescr->GetFormatKey())
1650 sal_Int32 nFormatKey = ::dbtools::getDefaultNumberFormat( pActFieldDescr->GetType(),
1651 pActFieldDescr->GetScale(),
1652 pActFieldDescr->IsCurrency(),
1653 Reference< XNumberFormatTypes>(GetView()->getController().getNumberFormatter()->getNumberFormatsSupplier()->getNumberFormats(),UNO_QUERY),
1654 GetView()->getLocale());
1656 pActFieldDescr->SetFormatKey(nFormatKey);
1659 pDescrWin->DisplayData( pActFieldDescr );
1662 OTableDesignView* OTableEditorCtrl::GetView() const
1664 return static_cast<OTableDesignView*>(GetParent()->GetParent());
1667 void OTableEditorCtrl::DeactivateCell(bool bUpdate)
1669 OTableRowView::DeactivateCell(bUpdate);
1670 // now we have to deactivate the field description
1671 long nRow(GetCurRow());
1672 if (pDescrWin)
1673 pDescrWin->SetReadOnly(bReadOnly || !SetDataPtr(nRow) || GetActRow()->IsReadOnly());
1676 bool OTableEditorCtrl::PreNotify( NotifyEvent& rNEvt )
1678 if (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS)
1680 if( pHelpTextCell && pHelpTextCell->HasChildPathFocus() )
1681 m_eChildFocus = HELPTEXT;
1682 else if( pDescrCell && pDescrCell->HasChildPathFocus() )
1683 m_eChildFocus = DESCRIPTION;
1684 else if(pNameCell && pNameCell->HasChildPathFocus() )
1685 m_eChildFocus = NAME;
1686 else
1687 m_eChildFocus = ROW;
1690 return OTableRowView::PreNotify(rNEvt);
1693 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */