/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_dbaccess.hxx" #ifndef DBAUI_TABLEEDITORCONTROL_HXX #include "TEditControl.hxx" #endif #ifndef _TOOLS_DEBUG_HXX #include #endif #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDBCX_XALTERTABLE_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ #include #endif #ifndef _COM_SUN_STAR_UTIL_XNUMBERFORMATTYPES_HPP_ #include #endif #ifndef _DBU_TBL_HRC_ #include "dbu_tbl.hrc" #endif #ifndef DBACCESS_SHARED_DBUSTRINGS_HRC #include "dbustrings.hrc" #endif #ifndef DBACCESS_UI_BROWSER_ID_HXX #include "browserids.hxx" #endif #ifndef _DBA_DBACCESS_HELPID_HRC_ #include "dbaccess_helpid.hrc" #endif #ifndef _COMPHELPER_TYPES_HXX_ #include #endif #ifndef DBAUI_FIELDDESCRIPTIONCONTROL_HXX #include "FieldDescControl.hxx" #endif #ifndef DBAUI_FIELDDESCRIPTIONS_HXX #include "FieldDescriptions.hxx" #endif #ifndef _SV_MSGBOX_HXX #include #endif #ifndef DBAUI_TABLEUNDO_HXX #include "TableUndo.hxx" #endif #ifndef DBUI_TABLECONTROLLER_HXX #include "TableController.hxx" #endif #ifndef _CONNECTIVITY_DBTOOLS_HXX_ #include #endif #ifndef DBAUI_SQLNAMEEDIT_HXX #include "SqlNameEdit.hxx" #endif #ifndef DBAUI_TABLEROW_EXCHANGE_HXX #include "TableRowExchange.hxx" #endif #ifndef _SOT_STORAGE_HXX #include #endif #ifndef DBAUI_TOOLS_HXX #include "UITools.hxx" #endif #ifndef DBAUI_FIELDDESCRIPTIONCONTROL_HXX #include "FieldDescControl.hxx" #endif #ifndef DBAUI_TABLEFIELDCONTROL_HXX #include "TableFieldControl.hxx" #endif using namespace ::dbaui; using namespace ::comphelper; using namespace ::svt; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; using namespace ::com::sun::star::io; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::util; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::sdbc; using namespace ::com::sun::star::sdbcx; using namespace ::com::sun::star::sdb; namespace dbaui { extern String GetTypeString( sal_uInt16 nType ); } //============================================================================== // TYPEINIT1(OTableEditorCtrl, DBView); DBG_NAME(OTableEditorCtrl) //============================================================================== #define HANDLE_ID 0 // Anzahl Spalten beim Neuanlegen #define NEWCOLS 128 // default Spaltenbreiten #define FIELDNAME_WIDTH 100 #define FIELDTYPE_WIDTH 150 #define FIELDDESCR_WIDTH 300 // Maximale Eingabelaenge im Beschreibungsfeld #define MAX_DESCR_LEN 256 #define CONTROL_SPACING_X 18 // 6 #define CONTROL_SPACING_Y 5 #define CONTROL_HEIGHT 20 #define CONTROL_WIDTH_1 140 // 100 #define CONTROL_WIDTH_2 100 // 60 #define CONTROL_WIDTH_3 250 #define CONTROL_WIDTH_4 (CONTROL_WIDTH_3 - CONTROL_HEIGHT - 5) //================================================================== DBG_NAME(ClipboardInvalidator) //------------------------------------------------------------------ OTableEditorCtrl::ClipboardInvalidator::ClipboardInvalidator(ULONG nTimeout,OTableEditorCtrl* _pOwner) : m_pOwner(_pOwner) { DBG_CTOR(ClipboardInvalidator,NULL); m_aInvalidateTimer.SetTimeout(nTimeout); m_aInvalidateTimer.SetTimeoutHdl(LINK(this, OTableEditorCtrl::ClipboardInvalidator, OnInvalidate)); m_aInvalidateTimer.Start(); } //------------------------------------------------------------------ OTableEditorCtrl::ClipboardInvalidator::~ClipboardInvalidator() { m_aInvalidateTimer.Stop(); DBG_DTOR(ClipboardInvalidator,NULL); } //------------------------------------------------------------------ IMPL_LINK(OTableEditorCtrl::ClipboardInvalidator, OnInvalidate, void*, EMPTYARG) { m_pOwner->GetView()->getController().InvalidateFeature(SID_CUT); m_pOwner->GetView()->getController().InvalidateFeature(SID_COPY); m_pOwner->GetView()->getController().InvalidateFeature(SID_PASTE); return 0L; } //================================================================== void OTableEditorCtrl::Init() { DBG_CHKTHIS(OTableEditorCtrl,NULL); OTableRowView::Init(); ////////////////////////////////////////////////////////////////////// // Soll der Entwurf ReadOnly geoeffnet werden ? sal_Bool bRead(GetView()->getController().isReadOnly()); SetReadOnly( bRead ); ////////////////////////////////////////////////////////////////////// // Spalten einfuegen String aColumnName( ModuleRes(STR_TAB_FIELD_COLUMN_NAME) ); InsertDataColumn( 1, aColumnName, FIELDNAME_WIDTH ); aColumnName = String( ModuleRes(STR_TAB_FIELD_COLUMN_DATATYPE) ); InsertDataColumn( 2, aColumnName, FIELDTYPE_WIDTH ); aColumnName = String( ModuleRes(STR_TAB_FIELD_DESCR) ); InsertDataColumn( 3, aColumnName, FIELDDESCR_WIDTH ); InitCellController(); ////////////////////////////////////////////////////////////////////// // Zeilen einfuegen RowInserted(0, m_pRowList->size(), sal_True); } //================================================================== void OTableEditorCtrl::UpdateAll() { DBG_CHKTHIS(OTableEditorCtrl,NULL); RowRemoved(0, GetRowCount(), sal_False); m_nDataPos = 0; InvalidateFeatures(); Invalidate(); } //================================================================== OTableEditorCtrl::OTableEditorCtrl(Window* pWindow) :OTableRowView(pWindow) ,pNameCell(NULL) ,pTypeCell(NULL) ,pDescrCell(NULL) ,pDescrWin(NULL) ,nIndexEvent(0) ,nCutEvent(0) ,nPasteEvent(0) ,nDeleteEvent(0) ,nInsNewRowsEvent(0) ,nInvalidateTypeEvent(0) ,nEntryNotFoundEvent(0) ,m_eChildFocus(NONE) ,nOldDataPos(-1) ,bSaveOnMove(sal_True) ,bReadOnly(sal_True) ,m_aInvalidate(500,this) { DBG_CTOR(OTableEditorCtrl,NULL); SetHelpId(HID_TABDESIGN_BACKGROUND); GetDataWindow().SetHelpId(HID_CTL_TABLEEDIT); m_pRowList = GetView()->getController().getRows(); m_nDataPos = 0; } //------------------------------------------------------------------------------ SfxUndoManager* OTableEditorCtrl::GetUndoManager() const { return GetView()->getController().getUndoMgr(); } //------------------------------------------------------------------------------ BOOL OTableEditorCtrl::IsReadOnly() { DBG_CHKTHIS(OTableEditorCtrl,NULL); return bReadOnly; } //------------------------------------------------------------------------------ void OTableEditorCtrl::SetReadOnly( sal_Bool bRead ) { // nix zu tun ? if (bRead == IsReadOnly()) // diese Abfrage ist wichtig, da die zugrundeliegende Def sonst im folgenden gelockt oder ge-unlocked wird, obwohl es // nicht notwendig waere (und was schlimmer ist, das wuerde dann auch nicht wieder rueckgaengig gemacht) return; DBG_CHKTHIS(OTableEditorCtrl,NULL); bReadOnly = bRead; ////////////////////////////////////////////////////////////////////// // Aktive Zelle disablen long nRow(GetCurRow()); sal_uInt16 nCol(GetCurColumnId()); DeactivateCell(); ////////////////////////////////////////////////////////////////////// // ::com::sun::star::beans::Property Controls disablen // if (pDescrWin) // pDescrWin->SetReadOnly(bReadOnly || !SetDataPtr(nRow) || GetActRow()->IsReadOnly()); ////////////////////////////////////////////////////////////////////// // Cursor des Browsers anpassen BrowserMode nMode(BROWSER_COLUMNSELECTION | BROWSER_MULTISELECTION | BROWSER_KEEPSELECTION | BROWSER_HLINESFULL | BROWSER_VLINESFULL|BROWSER_AUTOSIZE_LASTCOL); if( !bReadOnly ) nMode |= BROWSER_HIDECURSOR; SetMode(nMode); if( !bReadOnly ) ActivateCell( nRow, nCol ); } //------------------------------------------------------------------------------ void OTableEditorCtrl::InitCellController() { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Zelle Feldname xub_StrLen nMaxTextLen = EDIT_NOLIMIT; ::rtl::OUString sExtraNameChars; Reference xCon; try { xCon = GetView()->getController().getConnection(); Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>(); nMaxTextLen = ((xub_StrLen)xMetaData.is() ? static_cast(xMetaData->getMaxColumnNameLength()) : 0); if( nMaxTextLen == 0 ) nMaxTextLen = EDIT_NOLIMIT; sExtraNameChars = xMetaData.is() ? xMetaData->getExtraNameCharacters() : ::rtl::OUString(); } catch(SQLException&) { OSL_ASSERT(!"getMaxColumnNameLength"); } pNameCell = new OSQLNameEdit( &GetDataWindow(), sExtraNameChars,WB_LEFT ); pNameCell->SetMaxTextLen( nMaxTextLen ); pNameCell->setCheck( isSQL92CheckEnabled(xCon) ); ////////////////////////////////////////////////////////////////////// // Zelle Typ pTypeCell = new ListBoxControl( &GetDataWindow() ); pTypeCell->SetDropDownLineCount( 15 ); ////////////////////////////////////////////////////////////////////// // Zelle Beschreibung pDescrCell = new Edit( &GetDataWindow(), WB_LEFT ); pDescrCell->SetMaxTextLen( MAX_DESCR_LEN ); pNameCell->SetHelpId(HID_TABDESIGN_NAMECELL); pTypeCell->SetHelpId(HID_TABDESIGN_TYPECELL); pDescrCell->SetHelpId(HID_TABDESIGN_COMMENTCELL); Size aHeight; const Control* pControls[] = { pTypeCell,pDescrCell,pNameCell}; for(sal_Size i= 0; i < sizeof(pControls)/sizeof(pControls[0]);++i) { const Size aTemp( pControls[i]->GetOptimalSize(WINDOWSIZE_PREFERRED) ); if ( aTemp.Height() > aHeight.Height() ) aHeight.Height() = aTemp.Height(); } // for(int i= 0; i < sizeof(pControls)/sizeof(pControls[0]);++i SetDataRowHeight(aHeight.Height()); ClearModified(); } //------------------------------------------------------------------------------ void OTableEditorCtrl::ClearModified() { DBG_CHKTHIS(OTableEditorCtrl,NULL); pNameCell->ClearModifyFlag(); pDescrCell->ClearModifyFlag(); pTypeCell->SaveValue(); } //------------------------------------------------------------------------------ OTableEditorCtrl::~OTableEditorCtrl() { DBG_DTOR(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Undo-Manager zuruecksetzen GetUndoManager()->Clear(); ////////////////////////////////////////////////////////////////////// // Moegliche Events aus Queue entfernen if( nCutEvent ) Application::RemoveUserEvent( nCutEvent ); if( nPasteEvent ) Application::RemoveUserEvent( nPasteEvent ); if( nDeleteEvent ) Application::RemoveUserEvent( nDeleteEvent ); if( nInsNewRowsEvent ) Application::RemoveUserEvent( nInsNewRowsEvent ); if( nInvalidateTypeEvent ) Application::RemoveUserEvent( nInvalidateTypeEvent ); if( nEntryNotFoundEvent ) Application::RemoveUserEvent( nEntryNotFoundEvent ); ////////////////////////////////////////////////////////////////////// // Controltypen zerstoeren delete pNameCell; delete pTypeCell; delete pDescrCell; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::SetDataPtr( long nRow ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); if(nRow == -1) return sal_False; OSL_ENSURE((xub_StrLen)nRow < m_pRowList->size(),"Row is greater than size!"); if(nRow >= (long)m_pRowList->size()) return sal_False; pActRow = (*m_pRowList)[nRow]; return pActRow != NULL; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::SeekRow(long _nRow) { // die Basisklasse braucht den Aufruf, da sie sich dort merkt, welche Zeile gepainted wird EditBrowseBox::SeekRow(_nRow); DBG_CHKTHIS(OTableEditorCtrl,NULL); m_nCurrentPos = _nRow; return SetDataPtr(_nRow); } //------------------------------------------------------------------------------ void OTableEditorCtrl::PaintCell(OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const { DBG_CHKTHIS(OTableEditorCtrl,NULL); String aText( GetCellText( m_nCurrentPos, nColumnId )); Point aPos(rRect.TopLeft()); Size TxtSize(GetDataWindow().GetTextWidth(aText), GetDataWindow().GetTextHeight()); if (aPos.X() < rRect.Right() || aPos.X() + TxtSize.Width() > rRect.Right() || aPos.Y() < rRect.Top() || aPos.Y() + TxtSize.Height() > rRect.Bottom()) rDev.SetClipRegion( rRect ); rDev.DrawText(aPos, aText); if (rDev.IsClipRegion()) rDev.SetClipRegion(); // rDev.DrawText(rRect.TopLeft(), aText); // rDev.SetClipRegion( ); } //------------------------------------------------------------------------------ CellController* OTableEditorCtrl::GetController(long nRow, sal_uInt16 nColumnId) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Wenn EditorCtrl ReadOnly ist, darf nicht editiert werden Reference xTable = GetView()->getController().getTable(); if (IsReadOnly() || ( xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_TYPE) && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == ::rtl::OUString::createFromAscii("VIEW"))) return NULL; ////////////////////////////////////////////////////////////////////// // Wenn Zeile ReadOnly ist, darf sie nicht editiert werden SetDataPtr( nRow ); if( pActRow->IsReadOnly() ) return NULL; OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr(); switch (nColumnId) { case FIELD_NAME: return new EditCellController( pNameCell ); case FIELD_TYPE: if (pActFieldDescr && (pActFieldDescr->GetName().getLength() != 0)) return new ListBoxCellController( pTypeCell ); else return NULL; case FIELD_DESCR: if (pActFieldDescr && (pActFieldDescr->GetName().getLength() != 0)) return new EditCellController( pDescrCell ); else return NULL; default: return NULL; } } //------------------------------------------------------------------------------ void OTableEditorCtrl::InitController(CellControllerRef&, long nRow, sal_uInt16 nColumnId) { DBG_CHKTHIS(OTableEditorCtrl,NULL); SeekRow( nRow == -1 ? GetCurRow() : nRow); OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr(); String aInitString; switch (nColumnId) { case FIELD_NAME: if( pActFieldDescr ) aInitString = pActFieldDescr->GetName(); pNameCell->SetText( aInitString ); pNameCell->SaveValue(); break; case FIELD_TYPE: { if ( pActFieldDescr && pActFieldDescr->getTypeInfo() ) aInitString = pActFieldDescr->getTypeInfo()->aUIName; ////////////////////////////////////////////////////////////// // Anpassen des ComboBoxInhalts pTypeCell->Clear(); if( !pActFieldDescr ) break; const OTypeInfoMap* pTypeInfo = GetView()->getController().getTypeInfo(); OTypeInfoMap::const_iterator aIter = pTypeInfo->begin(); OTypeInfoMap::const_iterator aEnd = pTypeInfo->end(); for(;aIter != aEnd;++aIter) pTypeCell->InsertEntry( aIter->second->aUIName ); pTypeCell->SelectEntry( aInitString ); } break; case FIELD_DESCR: if( pActFieldDescr ) aInitString = pActFieldDescr->GetDescription(); pDescrCell->SetText( aInitString ); pDescrCell->SaveValue(); break; } } //------------------------------------------------------------------------------ EditBrowseBox::RowStatus OTableEditorCtrl::GetRowStatus(long nRow) const { DBG_CHKTHIS(OTableEditorCtrl,NULL); ( (OTableEditorCtrl*)this )->SetDataPtr( nRow ); if( !pActRow ) return EditBrowseBox::CLEAN; if (nRow >= 0 && nRow == m_nDataPos) { if( pActRow->IsPrimaryKey() ) return EditBrowseBox::CURRENT_PRIMARYKEY; return EditBrowseBox::CURRENT; } else { if( pActRow->IsPrimaryKey() ) return EditBrowseBox::PRIMARYKEY; return EditBrowseBox::CLEAN; } } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::SaveCurRow() { DBG_CHKTHIS(OTableEditorCtrl,NULL); if (GetFieldDescr(GetCurRow()) == NULL) // in der Zeile, in der ich mich i.A. befinde, stehen keine Daten return sal_True; if (!SaveModified()) return sal_False; SetDataPtr(GetCurRow()); pDescrWin->SaveData( pActRow->GetActFieldDescr() ); return sal_True; } //------------------------------------------------------------------------------ void OTableEditorCtrl::DisplayData(long nRow, sal_Bool bGrabFocus) { // zur richtigen Zelle fahren SetDataPtr(nRow); // Editier-Modus temporaer aus sal_Bool bWasEditing = IsEditing(); if (bWasEditing) DeactivateCell(); CellControllerRef aTemp; InitController(aTemp, nRow, FIELD_NAME); InitController(aTemp, nRow, FIELD_TYPE); InitController(aTemp, nRow, FIELD_DESCR); GoToRow(nRow); // das Description-Window aktualisieren GetView()->GetDescWin()->DisplayData(GetFieldDescr(nRow)); // neu zeichnen RowModified(nRow); // wieder an if (bWasEditing || bGrabFocus) ActivateCell(nRow, GetCurColumnId(), bGrabFocus); } //------------------------------------------------------------------------------ void OTableEditorCtrl::CursorMoved() { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Zeilenwechsel ? m_nDataPos = GetCurRow(); if( m_nDataPos != nOldDataPos && m_nDataPos != -1) { CellControllerRef aTemp; InitController(aTemp,m_nDataPos,FIELD_NAME); InitController(aTemp,m_nDataPos,FIELD_TYPE); InitController(aTemp,m_nDataPos,FIELD_DESCR); } OTableRowView::CursorMoved(); } //------------------------------------------------------------------------------ sal_Int32 OTableEditorCtrl::HasFieldName( const String& rFieldName ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); Reference xCon = GetView()->getController().getConnection(); Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>(); ::comphelper::UStringMixEqual bCase(xMetaData.is() ? xMetaData->supportsMixedCaseQuotedIdentifiers() : sal_True); ::std::vector< ::boost::shared_ptr >::iterator aIter = m_pRowList->begin(); ::std::vector< ::boost::shared_ptr >::iterator aEnd = m_pRowList->end(); OFieldDescription* pFieldDescr; sal_Int32 nCount(0); for(;aIter != aEnd;++aIter) { pFieldDescr = (*aIter)->GetActFieldDescr(); if( pFieldDescr && bCase(rFieldName,pFieldDescr->GetName())) nCount++; } return nCount; } // -------------------------------------------------------------------------------------- sal_Bool OTableEditorCtrl::SaveData(long nRow, sal_uInt16 nColId) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////// // Zellinhalte in Datenstruktur speichern SetDataPtr( nRow == -1 ? GetCurRow() : nRow); OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr(); switch( nColId) { ////////////////////////////////////////////////////////////// // Speichern Inhalt NameCell case FIELD_NAME: { ////////////////////////////////////////////////////////////// // Wenn kein Name, nichts machen String aName(pNameCell->GetText()); if( !aName.Len() ) { ////////////////////////////////////////////////////////////// // Wenn FieldDescr existiert, wurde Feld geloescht und alter Inhalt wird wiederhergestellt if (pActFieldDescr) { GetUndoManager()->AddUndoAction(new OTableEditorTypeSelUndoAct(this, nRow, FIELD_TYPE, pActFieldDescr->getTypeInfo())); SwitchType(TOTypeInfoSP()); pActFieldDescr = pActRow->GetActFieldDescr(); } else return sal_True; } if(pActFieldDescr) pActFieldDescr->SetName( aName ); pNameCell->ClearModifyFlag(); break; } ////////////////////////////////////////////////////////////// // Speichern Inhalt TypeCell case FIELD_TYPE: break; ////////////////////////////////////////////////////////////// // Speichern Inhalt DescrCell case FIELD_DESCR: { ////////////////////////////////////////////////////////////// // Wenn aktuelle Feldbeschreibung NULL, Default setzen if( !pActFieldDescr ) { pDescrCell->SetText(String()); pDescrCell->ClearModifyFlag(); } else pActFieldDescr->SetDescription( pDescrCell->GetText() ); break; } case FIELD_PROPERTY_DEFAULT: case FIELD_PROPERTY_REQUIRED: case FIELD_PROPERTY_TEXTLEN: case FIELD_PROPERTY_NUMTYPE: case FIELD_PROPERTY_AUTOINC: case FIELD_PROPERTY_LENGTH: case FIELD_PROPERTY_SCALE: case FIELD_PROPERTY_BOOL_DEFAULT: pDescrWin->SaveData(pActFieldDescr); if ( FIELD_PROPERTY_AUTOINC == nColId && pActFieldDescr->IsAutoIncrement() ) { OTableController& rController = GetView()->getController(); if ( rController.isAutoIncrementPrimaryKey() ) { pActFieldDescr->SetPrimaryKey( true ); InvalidateHandleColumn(); Invalidate(); } } break; } return sal_True; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::SaveModified() { DBG_CHKTHIS(OTableEditorCtrl,NULL); sal_uInt16 nColId = GetCurColumnId(); switch( nColId ) { ////////////////////////////////////////////////////////////// // NameCell case FIELD_NAME: { // removed the former duplicate-check. this is done in OTableDocShell::CheckDefConsistency now. // FS - 07.12.99 - 69575 } break; ////////////////////////////////////////////////////////////// // TypeCell case FIELD_TYPE: { ////////////////////////////////////////////////////////////////////// // Type umstellen resetType(); } break; } return sal_True; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::CursorMoving(long nNewRow, sal_uInt16 nNewCol) { DBG_CHKTHIS(OTableEditorCtrl,NULL); if (!EditBrowseBox::CursorMoving(nNewRow, nNewCol)) return sal_False; ////////////////////////////////////////////////////////////////////// // Wird nach SaveModified() gerufen, aktuelle Zeile ist noch die alte m_nDataPos = nNewRow; nOldDataPos = GetCurRow(); ////////////////////////////////////////////////////////////////////// // Marker umsetzen InvalidateStatusCell( nOldDataPos ); InvalidateStatusCell( m_nDataPos ); ////////////////////////////////////////////////////////////////////// // Daten des Propertyfensters speichern if( SetDataPtr(nOldDataPos) && pDescrWin) pDescrWin->SaveData( pActRow->GetActFieldDescr() ); ////////////////////////////////////////////////////////////////////// // Neue Daten im Propertyfenster anzeigen if( SetDataPtr(m_nDataPos) && pDescrWin) pDescrWin->DisplayData( pActRow->GetActFieldDescr() ); return sal_True; } //------------------------------------------------------------------------------ IMPL_LINK( OTableEditorCtrl, InvalidateFieldType, void*, /*EMPTYTAG*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); nInvalidateTypeEvent = 0; Invalidate( GetFieldRectPixel(nOldDataPos, FIELD_TYPE) ); return 0; } //------------------------------------------------------------------------------ IMPL_LINK( OTableEditorCtrl, EntryNotFound, void*, /*EMPTYTAG*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); nEntryNotFoundEvent = 0; ErrorBox( this, ModuleRes(ERR_INVALID_LISTBOX_ENTRY) ).Execute(); return 0; } //------------------------------------------------------------------------------ void OTableEditorCtrl::CellModified( long nRow, sal_uInt16 nColId ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////// // Wenn aktuelle Feldbeschreibung NULL, Default setzen if(nRow == -1) nRow = GetCurRow(); SetDataPtr( nRow ); OFieldDescription* pActFieldDescr = pActRow->GetActFieldDescr(); String sActionDescription; switch ( nColId ) { case FIELD_NAME: sActionDescription = String( ModuleRes( STR_CHANGE_COLUMN_NAME ) ); break; case FIELD_TYPE: sActionDescription = String( ModuleRes( STR_CHANGE_COLUMN_TYPE ) ); break; case FIELD_DESCR: sActionDescription = String( ModuleRes( STR_CHANGE_COLUMN_DESCRIPTION ) ); break; default: sActionDescription = String( ModuleRes( STR_CHANGE_COLUMN_ATTRIBUTE ) ); break; } GetUndoManager()->EnterListAction( sActionDescription, String() ); if (!pActFieldDescr) { const OTypeInfoMap* pTypeInfoMap = GetView()->getController().getTypeInfo(); if ( !pTypeInfoMap->empty() ) { OTypeInfoMap::const_iterator aTypeIter = pTypeInfoMap->find(DataType::VARCHAR); if ( aTypeIter == pTypeInfoMap->end() ) aTypeIter = pTypeInfoMap->begin(); pActRow->SetFieldType( aTypeIter->second ); } else pActRow->SetFieldType( GetView()->getController().getTypeInfoFallBack() ); nInvalidateTypeEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, InvalidateFieldType) ); pActFieldDescr = pActRow->GetActFieldDescr(); pDescrWin->DisplayData( pActFieldDescr ); GetUndoManager()->AddUndoAction( new OTableEditorTypeSelUndoAct(this, nRow, nColId+1, TOTypeInfoSP()) ); } if( nColId != FIELD_TYPE ) GetUndoManager()->AddUndoAction( new OTableDesignCellUndoAct(this, nRow, nColId) ); else { GetUndoManager()->AddUndoAction(new OTableEditorTypeSelUndoAct(this, GetCurRow(), nColId, GetFieldDescr(GetCurRow())->getTypeInfo())); resetType(); } SaveData(nRow,nColId); // SaveData could create a undo action as well GetUndoManager()->LeaveListAction(); RowModified(nRow); CellControllerRef xController(Controller()); if(xController.Is()) xController->SetModified(); ////////////////////////////////////////////////////////////////////// // Das ModifyFlag setzen GetView()->getController().setModified( sal_True ); InvalidateFeatures(); } // ----------------------------------------------------------------------------- void OTableEditorCtrl::resetType() { USHORT nPos = pTypeCell->GetSelectEntryPos(); if(nPos != LISTBOX_ENTRY_NOTFOUND) SwitchType( GetView()->getController().getTypeInfo(nPos) ); else SwitchType(TOTypeInfoSP()); } //------------------------------------------------------------------------------ void OTableEditorCtrl::CellModified() { DBG_CHKTHIS(OTableEditorCtrl,NULL); CellModified( GetCurRow(), GetCurColumnId() ); } // ----------------------------------------------------------------------------- void OTableEditorCtrl::InvalidateFeatures() { GetView()->getController().InvalidateFeature(SID_UNDO); GetView()->getController().InvalidateFeature(SID_REDO); GetView()->getController().InvalidateFeature(SID_SAVEDOC); } //------------------------------------------------------------------------------ void OTableEditorCtrl::Undo() { DBG_CHKTHIS(OTableEditorCtrl,NULL); InvalidateFeatures(); } //------------------------------------------------------------------------------ void OTableEditorCtrl::Redo() { DBG_CHKTHIS(OTableEditorCtrl,NULL); InvalidateFeatures(); } //------------------------------------------------------------------------------ void OTableEditorCtrl::CopyRows() { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // set to the right row and save it if( SetDataPtr(m_nDataPos) ) pDescrWin->SaveData( pActRow->GetActFieldDescr() ); ////////////////////////////////////////////////////////////////////// // Selektierte Zeilen in die ClipboardListe kopieren ::boost::shared_ptr pClipboardRow; ::boost::shared_ptr pRow; ::std::vector< ::boost::shared_ptr > vClipboardList; vClipboardList.reserve(GetSelectRowCount()); for( long nIndex=FirstSelectedRow(); nIndex >= 0 && nIndex < static_cast(m_pRowList->size()); nIndex=NextSelectedRow() ) { pRow = (*m_pRowList)[nIndex]; OSL_ENSURE(pRow,"OTableEditorCtrl::CopyRows: Row is NULL!"); if ( pRow && pRow->GetActFieldDescr() ) { pClipboardRow.reset(new OTableRow( *pRow )); vClipboardList.push_back( pClipboardRow); } } if(!vClipboardList.empty()) { OTableRowExchange* pData = new OTableRowExchange(vClipboardList); Reference< ::com::sun::star::datatransfer::XTransferable> xRef = pData; pData->CopyToClipboard(GetParent()); } } //------------------------------------------------------------------------------ String OTableEditorCtrl::GenerateName( const String& rName ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Basisnamen zum Anhaengen einer Numerierung erstellen String aBaseName; Reference xCon = GetView()->getController().getConnection(); Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>(); xub_StrLen nMaxTextLen((xub_StrLen)( xMetaData.is() ? xMetaData->getMaxColumnNameLength() : 0)); if( (rName.Len()+2) >nMaxTextLen ) aBaseName = rName.Copy( 0, nMaxTextLen-2 ); else aBaseName = rName; ////////////////////////////////////////////////////////////////////// // Namen durchnumerieren (bis 99) String aFieldName( rName); sal_Int32 i=1; while( HasFieldName(aFieldName) ) { aFieldName = aBaseName; aFieldName += String::CreateFromInt32(i); i++; } return aFieldName; } //------------------------------------------------------------------------------ void OTableEditorCtrl::InsertRows( long nRow ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ::std::vector< ::boost::shared_ptr > vInsertedUndoRedoRows; // need for undo/redo handling ////////////////////////////////////////////////////////////////////// // get rows from clipboard TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent())); if(aTransferData.HasFormat(SOT_FORMATSTR_ID_SBA_TABED)) { SotStorageStreamRef aStreamRef; aTransferData.GetSotStorageStream(SOT_FORMATSTR_ID_SBA_TABED,aStreamRef); if(aStreamRef.Is()) { aStreamRef->Seek(STREAM_SEEK_TO_BEGIN); aStreamRef->ResetError(); long nInsertRow = nRow; String aFieldName; ::boost::shared_ptr pRow; sal_Int32 nSize = 0; (*aStreamRef) >> nSize; vInsertedUndoRedoRows.reserve(nSize); for(sal_Int32 i=0;i < nSize;++i) { pRow.reset(new OTableRow()); (*aStreamRef) >> *pRow; pRow->SetReadOnly( sal_False ); sal_Int32 nType = pRow->GetActFieldDescr()->GetType(); if ( pRow->GetActFieldDescr() ) pRow->GetActFieldDescr()->SetType(GetView()->getController().getTypeInfoByType(nType)); ////////////////////////////////////////////////////////////////////// // Anpassen des Feldnamens aFieldName = GenerateName( pRow->GetActFieldDescr()->GetName() ); pRow->GetActFieldDescr()->SetName( aFieldName ); pRow->SetPos(nInsertRow); m_pRowList->insert( m_pRowList->begin()+nInsertRow,pRow ); vInsertedUndoRedoRows.push_back(::boost::shared_ptr(new OTableRow(*pRow))); nInsertRow++; } } } ////////////////////////////////////////////////////////////////////// // Beim RowInserted wird CursorMoved gerufen. // Die UI-Daten duerfen hier beim CursorMoved nicht gespeichert werden. bSaveOnMove = sal_False; RowInserted( nRow,vInsertedUndoRedoRows.size(),sal_True ); bSaveOnMove = sal_True; ////////////////////////////////////////////////////////////////////// // Undo-Action erzeugen GetUndoManager()->AddUndoAction( new OTableEditorInsUndoAct(this, nRow,vInsertedUndoRedoRows) ); GetView()->getController().setModified( sal_True ); InvalidateFeatures(); } //------------------------------------------------------------------------------ void OTableEditorCtrl::DeleteRows() { DBG_CHKTHIS(OTableEditorCtrl,NULL); OSL_ENSURE(GetView()->getController().isDropAllowed(),"Call of DeleteRows not valid here. Please check isDropAllowed!"); ////////////////////////////////////////////////////////////////////// // Undo-Action erzeugen GetUndoManager()->AddUndoAction( new OTableEditorDelUndoAct(this) ); ////////////////////////////////////////////////////////////////////// // Alle markierten Zeilen loeschen long nIndex = FirstSelectedRow(); nOldDataPos = nIndex; bSaveOnMove = sal_False; while( nIndex >= 0 && nIndex < static_cast(m_pRowList->size()) ) { ////////////////////////////////////////////////////////////////////// // Zeile entfernen m_pRowList->erase( m_pRowList->begin()+nIndex ); RowRemoved( nIndex, 1, sal_True ); ////////////////////////////////////////////////////////////////////// // Leerzeile am Ende wieder einfuegen m_pRowList->push_back( ::boost::shared_ptr(new OTableRow())); RowInserted( GetRowCount()-1, 1, sal_True ); nIndex = FirstSelectedRow(); } bSaveOnMove = sal_True; ////////////////////////////////////////////////////////////////////// // Erzwingen, dass der aktuelle Datensatz angezeigt wird m_nDataPos = GetCurRow(); InvalidateStatusCell( nOldDataPos ); InvalidateStatusCell( m_nDataPos ); SetDataPtr( m_nDataPos ); ActivateCell(); pDescrWin->DisplayData( pActRow->GetActFieldDescr() ); GetView()->getController().setModified( sal_True ); InvalidateFeatures(); } //------------------------------------------------------------------------------ void OTableEditorCtrl::InsertNewRows( long nRow ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); OSL_ENSURE(GetView()->getController().isAddAllowed(),"Call of InsertNewRows not valid here. Please check isAppendAllowed!"); ////////////////////////////////////////////////////////////////////// // Undo-Action erzeugen long nInsertRows = GetSelectRowCount(); if( !nInsertRows ) nInsertRows = 1; GetUndoManager()->AddUndoAction( new OTableEditorInsNewUndoAct(this, nRow, nInsertRows) ); ////////////////////////////////////////////////////////////////////// // Zahl der selektierten Zeilen werden neu eingefuegt for( long i=nRow; i<(nRow+nInsertRows); i++ ) m_pRowList->insert( m_pRowList->begin()+i ,::boost::shared_ptr(new OTableRow())); RowInserted( nRow, nInsertRows, sal_True ); GetView()->getController().setModified( sal_True ); InvalidateFeatures(); } //------------------------------------------------------------------------------ String OTableEditorCtrl::GetControlText( long nRow, sal_uInt16 nColId ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Controls des Browsers auslesen if( nColId < FIELD_FIRST_VIRTUAL_COLUMN ) { GoToRow( nRow ); GoToColumnId( nColId ); CellControllerRef xController = Controller(); if(xController.Is()) return xController->GetWindow().GetText(); else return GetCellText(nRow,nColId); } ////////////////////////////////////////////////////////////////////// // Controls der Tabpage Auslesen else return pDescrWin->GetControlText( nColId ); } //------------------------------------------------------------------------------ void OTableEditorCtrl::SetControlText( long nRow, sal_uInt16 nColId, const String& rText ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Controls des Browsers setzen if( nColId < FIELD_FIRST_VIRTUAL_COLUMN ) { GoToRow( nRow ); GoToColumnId( nColId ); CellControllerRef xController = Controller(); if(xController.Is()) xController->GetWindow().SetText( rText ); else RowModified(nRow,nColId); } ////////////////////////////////////////////////////////////////////// // Controls der Tabpage setzen else { pDescrWin->SetControlText( nColId, rText ); } } //------------------------------------------------------------------------------ void OTableEditorCtrl::SetCellData( long nRow, sal_uInt16 nColId, const TOTypeInfoSP& _pTypeInfo ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Aktuellen Datenzeiger umsetzen if( nRow == -1 ) nRow = GetCurRow(); OFieldDescription* pFieldDescr = GetFieldDescr( nRow ); if( !pFieldDescr && nColId != FIELD_TYPE) return; ////////////////////////////////////////////////////////////////////// // Einzelne Felder setzen switch( nColId ) { case FIELD_TYPE: SwitchType( _pTypeInfo ); break; default: OSL_ENSURE(sal_False, "OTableEditorCtrl::SetCellData: invalid column!"); } SetControlText(nRow,nColId,_pTypeInfo.get() ? _pTypeInfo->aUIName : ::rtl::OUString()); } //------------------------------------------------------------------------------ void OTableEditorCtrl::SetCellData( long nRow, sal_uInt16 nColId, const ::com::sun::star::uno::Any& _rNewData ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Aktuellen Datenzeiger umsetzen if( nRow == -1 ) nRow = GetCurRow(); OFieldDescription* pFieldDescr = GetFieldDescr( nRow ); if( !pFieldDescr && nColId != FIELD_TYPE) return; String sValue; ////////////////////////////////////////////////////////////////////// // Einzelne Felder setzen switch( nColId ) { case FIELD_NAME: sValue = ::comphelper::getString(_rNewData); pFieldDescr->SetName( sValue ); break; case FIELD_TYPE: OSL_ENSURE(sal_False, "OTableEditorCtrl::SetCellData: invalid column!"); break; case FIELD_DESCR: pFieldDescr->SetDescription( sValue = ::comphelper::getString(_rNewData) ); break; case FIELD_PROPERTY_DEFAULT: pFieldDescr->SetControlDefault( _rNewData ); sValue = GetView()->GetDescWin()->getGenPage()->getFieldControl()->getControlDefault(pFieldDescr); break; case FIELD_PROPERTY_REQUIRED: { sValue = ::comphelper::getString(_rNewData); pFieldDescr->SetIsNullable( sValue.ToInt32() ); } break; case FIELD_PROPERTY_TEXTLEN: case FIELD_PROPERTY_LENGTH: { sValue = ::comphelper::getString(_rNewData); pFieldDescr->SetPrecision( sValue.ToInt32() ); } break; case FIELD_PROPERTY_NUMTYPE: // pFieldDescr->SetNumType( _rNewData ); OSL_ENSURE(sal_False, "OTableEditorCtrl::SetCellData: invalid column!"); break; case FIELD_PROPERTY_AUTOINC: { String strYes(ModuleRes(STR_VALUE_YES)); sValue = ::comphelper::getString(_rNewData); pFieldDescr->SetAutoIncrement(sValue.Equals(strYes)); } break; case FIELD_PROPERTY_SCALE: { sValue = ::comphelper::getString(_rNewData); pFieldDescr->SetScale(sValue.ToInt32()); } break; case FIELD_PROPERTY_BOOL_DEFAULT: sValue = GetView()->GetDescWin()->BoolStringPersistent(::comphelper::getString(_rNewData)); pFieldDescr->SetControlDefault(makeAny(::rtl::OUString(sValue))); break; case FIELD_PROPERTY_FORMAT: { sValue = ::comphelper::getString(_rNewData); pFieldDescr->SetFormatKey(sValue.ToInt32()); } break; } SetControlText(nRow,nColId,sValue); } //------------------------------------------------------------------------------ Any OTableEditorCtrl::GetCellData( long nRow, sal_uInt16 nColId ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); OFieldDescription* pFieldDescr = GetFieldDescr( nRow ); if( !pFieldDescr ) return Any(); ////////////////////////////////////////////////////////////////////// // Aktuellen Datenzeiger umsetzen if( nRow==-1 ) nRow = GetCurRow(); SetDataPtr( nRow ); static const String strYes(ModuleRes(STR_VALUE_YES)); static const String strNo(ModuleRes(STR_VALUE_NO)); ::rtl::OUString sValue; ////////////////////////////////////////////////////////////////////// // Einzelne Felder auslesen switch( nColId ) { case FIELD_NAME: sValue = pFieldDescr->GetName(); break; case FIELD_TYPE: if ( pFieldDescr->getTypeInfo() ) sValue = pFieldDescr->getTypeInfo()->aUIName; break; case FIELD_DESCR: sValue = pFieldDescr->GetDescription(); break; case FIELD_PROPERTY_DEFAULT: return pFieldDescr->GetControlDefault(); case FIELD_PROPERTY_REQUIRED: sValue = pFieldDescr->GetIsNullable() == ColumnValue::NULLABLE ? strYes : strNo; break; case FIELD_PROPERTY_TEXTLEN: case FIELD_PROPERTY_LENGTH: sValue = String::CreateFromInt32(pFieldDescr->GetPrecision()); break; case FIELD_PROPERTY_NUMTYPE: OSL_ENSURE(sal_False, "OTableEditorCtrl::GetCellData: invalid column!"); // return pFieldDescr->GetNumType(); case FIELD_PROPERTY_AUTOINC: sValue = pFieldDescr->IsAutoIncrement() ? strYes : strNo; break; case FIELD_PROPERTY_SCALE: sValue = String::CreateFromInt32(pFieldDescr->GetScale()); break; case FIELD_PROPERTY_BOOL_DEFAULT: sValue = GetView()->GetDescWin()->BoolStringUI(::comphelper::getString(pFieldDescr->GetControlDefault())); break; case FIELD_PROPERTY_FORMAT: sValue = String::CreateFromInt32(pFieldDescr->GetFormatKey()); break; } return makeAny(sValue); } //------------------------------------------------------------------------------ String OTableEditorCtrl::GetCellText( long nRow, sal_uInt16 nColId ) const { DBG_CHKTHIS(OTableEditorCtrl,NULL); ::rtl::OUString sCellText; const_cast< OTableEditorCtrl* >( this )->GetCellData( nRow, nColId ) >>= sCellText; return sCellText; } //------------------------------------------------------------------------------ sal_uInt32 OTableEditorCtrl::GetTotalCellWidth(long nRow, sal_uInt16 nColId) { DBG_CHKTHIS(OTableEditorCtrl,NULL); return GetTextWidth(GetCellText(nRow, nColId)) + 2 * GetTextWidth('0'); } //------------------------------------------------------------------------------ OFieldDescription* OTableEditorCtrl::GetFieldDescr( long nRow ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); std::vector< ::boost::shared_ptr >::size_type nListCount( m_pRowList->size()); if( (nRow<0) || (sal::static_int_cast< unsigned long >(nRow)>=nListCount) ) { OSL_ENSURE(0,"(nRow<0) || (nRow>=nListCount)"); return NULL; } ::boost::shared_ptr pRow = (*m_pRowList)[ nRow ]; if( !pRow ) return NULL; return pRow->GetActFieldDescr(); } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsCutAllowed( long nRow ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); sal_Bool bIsCutAllowed = (GetView()->getController().isAddAllowed() && GetView()->getController().isDropAllowed()) || GetView()->getController().isAlterAllowed(); if(bIsCutAllowed) { if(m_eChildFocus == DESCRIPTION) bIsCutAllowed = pDescrCell->GetSelected().Len() != 0; else if(m_eChildFocus == NAME) bIsCutAllowed = pNameCell->GetSelected().Len() != 0; else if(m_eChildFocus == ROW) // only rows are selected for cutting so we look if all rows are valid // wwe don't waant to copy empty rows here bIsCutAllowed = IsCopyAllowed(nRow); else bIsCutAllowed = sal_False; } // Reference xTable = GetView()->getController().getTable(); // if( !IsCopyAllowed(nRow) || (xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == ::rtl::OUString::createFromAscii("VIEW"))) // return sal_False; // return bCutAllowed && IsDeleteAllowed( nRow ); return bIsCutAllowed; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsCopyAllowed( long /*nRow*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); sal_Bool bIsCopyAllowed = sal_False; if(m_eChildFocus == DESCRIPTION) bIsCopyAllowed = pDescrCell->GetSelected().Len() != 0; else if(m_eChildFocus == NAME) bIsCopyAllowed = pNameCell->GetSelected().Len() != 0; else if(m_eChildFocus == ROW) { Reference xTable = GetView()->getController().getTable(); if( !GetSelectRowCount() || (xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == ::rtl::OUString::createFromAscii("VIEW"))) return sal_False; ////////////////////////////////////////////////////////////////////// // Wenn eine der markierten Zeilen leer ist, kein Copy moeglich ::boost::shared_ptr pRow; long nIndex = FirstSelectedRow(); while( nIndex >= 0 && nIndex < static_cast(m_pRowList->size()) ) { pRow = (*m_pRowList)[nIndex]; if( !pRow->GetActFieldDescr() ) return sal_False; nIndex = NextSelectedRow(); } bIsCopyAllowed = sal_True; } return bIsCopyAllowed; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsPasteAllowed( long /*nRow*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); sal_Bool bAllowed = GetView()->getController().isAddAllowed(); if ( bAllowed ) { TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent())); sal_Bool bRowFormat = aTransferData.HasFormat(SOT_FORMATSTR_ID_SBA_TABED); if ( m_eChildFocus == ROW ) bAllowed = bRowFormat; else bAllowed = !bRowFormat && aTransferData.HasFormat(SOT_FORMAT_STRING); } return bAllowed; } //------------------------------------------------------------------------------ void OTableEditorCtrl::cut() { if(m_eChildFocus == NAME) { if(GetView()->getController().isAlterAllowed()) { SaveData(-1,FIELD_NAME); pNameCell->Cut(); CellModified(-1,FIELD_NAME); } } else if(m_eChildFocus == DESCRIPTION) { if(GetView()->getController().isAlterAllowed()) { SaveData(-1,FIELD_DESCR); pDescrCell->Cut(); CellModified(-1,FIELD_DESCR); } } else if(m_eChildFocus == ROW) { if (nCutEvent) Application::RemoveUserEvent(nCutEvent); nCutEvent = Application::PostUserEvent(LINK(this, OTableEditorCtrl, DelayedCut)); } } //------------------------------------------------------------------------------ void OTableEditorCtrl::copy() { if(GetSelectRowCount()) OTableRowView::copy(); else if(m_eChildFocus == NAME) pNameCell->Copy(); else if(m_eChildFocus == DESCRIPTION) pDescrCell->Copy(); } //------------------------------------------------------------------------------ void OTableEditorCtrl::paste() { TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromSystemClipboard(GetParent())); if(aTransferData.HasFormat(SOT_FORMATSTR_ID_SBA_TABED)) { if( nPasteEvent ) Application::RemoveUserEvent( nPasteEvent ); nPasteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedPaste) ); } else if(m_eChildFocus == NAME) { if(GetView()->getController().isAlterAllowed()) { pNameCell->Paste(); CellModified(); } } else if(m_eChildFocus == DESCRIPTION) { if(GetView()->getController().isAlterAllowed()) { pDescrCell->Paste(); CellModified(); } } } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsDeleteAllowed( long /*nRow*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); return GetSelectRowCount() != 0 && GetView()->getController().isDropAllowed(); // Reference xTable = GetView()->getController().getTable(); // if( !GetSelectRowCount() || (xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == ::rtl::OUString::createFromAscii("VIEW"))) // return sal_False; // // // Wenn nur Felder hinzugefuegt werden duerfen, Delete nur auf neuen Feldern // Reference xCon = GetView()->getController().getConnection(); // Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : NULL; // // return !(xTable.is() && xTable->getPropertySetInfo()->getPropertyByName(PROPERTY_NAME).Attributes & PropertyAttribute::READONLY) || // ( xMetaData.is() && xMetaData->supportsAlterTableWithAddColumn() && xMetaData->supportsAlterTableWithDropColumn()); } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsInsertNewAllowed( long nRow ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); sal_Bool bInsertNewAllowed = GetView()->getController().isAddAllowed(); ////////////////////////////////////////////////////////////// // Wenn nur Felder hinzugefuegt werden duerfen, Paste nur in neue Felder if (bInsertNewAllowed && !GetView()->getController().isDropAllowed()) { SetDataPtr(nRow); if( GetActRow()->IsReadOnly() ) return sal_False; } return bInsertNewAllowed; } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsPrimaryKeyAllowed( long /*nRow*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); if( !GetSelectRowCount() ) return sal_False; OTableController& rController = GetView()->getController(); try { Reference xCon = rController.getConnection(); Reference< XDatabaseMetaData> xMetaData = xCon.is() ? xCon->getMetaData() : Reference< XDatabaseMetaData>(); if(!xMetaData.is() || !xMetaData->supportsCoreSQLGrammar()) return sal_False; // no primary keys allowed } catch(SQLException&) { OSL_ASSERT(!"supportsCoreSQLGrammar"); } Reference xTable = rController.getTable(); ////////////////////////////////////////////////////////////// // Key darf nicht veraendert werden // Dies gilt jedoch nur, wenn die Tabelle nicht neu ist und keine ::com::sun::star::sdbcx::View. Ansonsten wird kein DROP ausgeführt if(xTable.is() && ::comphelper::getString(xTable->getPropertyValue(PROPERTY_TYPE)) == ::rtl::OUString::createFromAscii("VIEW")) return sal_False; ////////////////////////////////////////////////////////////// // Wenn leeres Feld, kein PrimKey // Eintrag wird nur erlaubt, wenn // - kein leerer Eintrag in der Selection ist // - kein Eintrag vom Typ Memo oder Image ist // - kein DROP erlaubt ist (s.o.) und die Spalte noch kein Required (not null) gesetzt hatte. long nIndex = FirstSelectedRow(); ::boost::shared_ptr pRow; while( nIndex >= 0 && nIndex < static_cast(m_pRowList->size()) ) { pRow = (*m_pRowList)[nIndex]; OFieldDescription* pFieldDescr = pRow->GetActFieldDescr(); if(!pFieldDescr) return sal_False; else { ////////////////////////////////////////////////////////////// // Wenn Feldtyp Memo oder Image, kein PrimKey // oder wenn Spalten nicht gedroped werden können und das Required Flag ist nicht gesetzt // oder wenn eine ::com::sun::star::sdbcx::View vorhanden ist und das Required Flag nicht gesetzt ist TOTypeInfoSP pTypeInfo = pFieldDescr->getTypeInfo(); if( pTypeInfo->nSearchType == ColumnSearch::NONE || (pFieldDescr->IsNullable() && pRow->IsReadOnly()) ) return sal_False; } nIndex = NextSelectedRow(); } return sal_True; } //------------------------------------------------------------------------------ void OTableEditorCtrl::Command(const CommandEvent& rEvt) { DBG_CHKTHIS(OTableEditorCtrl,NULL); switch (rEvt.GetCommand()) { case COMMAND_CONTEXTMENU: { Point aMenuPos( rEvt.GetMousePosPixel() ); if (!rEvt.IsMouseEvent()) { if ( 1 == GetSelectColumnCount() ) { sal_uInt16 nSelId = GetColumnId( sal::static_int_cast< USHORT >( FirstSelectedColumn() ) ); ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, sal_False ) ); aMenuPos = aColRect.TopCenter(); } else if ( GetSelectRowCount() > 0 ) { ::Rectangle aColRect( GetFieldRectPixel( FirstSelectedRow(), HANDLE_ID, sal_True ) ); aMenuPos = aColRect.TopCenter(); } else { OTableRowView::Command(rEvt); return; } } ////////////////////////////////////////////////////////////// // Kontextmenu einblenden if( !IsReadOnly() ) { sal_uInt16 nColId = GetColumnAtXPosPixel(aMenuPos.X()); long nRow = GetRowAtYPosPixel(aMenuPos.Y()); if ( HANDLE_ID != nColId ) { if ( nRow < 0 && nColId != BROWSER_INVALIDID ) { // hit the header if ( 3 != nColId ) { // 3 would mean the last column, and this last column is auto-sized if ( !IsColumnSelected( nColId ) ) SelectColumnId( nColId ); PopupMenu aContextMenu( ModuleRes( RID_QUERYCOLPOPUPMENU ) ); aContextMenu.EnableItem( SID_DELETE, sal_False ); aContextMenu.RemoveDisabledEntries(sal_True, sal_True); switch ( aContextMenu.Execute( this, aMenuPos ) ) { case ID_BROWSER_COLWIDTH: adjustBrowseBoxColumnWidth( this, nColId ); break; } } } } else { PopupMenu aContextMenu(ModuleRes(RID_TABLEDESIGNROWPOPUPMENU)); aContextMenu.EnableItem( SID_CUT, IsCutAllowed(nRow) ); aContextMenu.EnableItem( SID_COPY, IsCopyAllowed(nRow) ); aContextMenu.EnableItem( SID_PASTE, IsPasteAllowed(nRow) ); aContextMenu.EnableItem( SID_DELETE, IsDeleteAllowed(nRow) ); aContextMenu.EnableItem( SID_TABLEDESIGN_TABED_PRIMARYKEY, IsPrimaryKeyAllowed(nRow) ); aContextMenu.EnableItem( SID_TABLEDESIGN_INSERTROWS, IsInsertNewAllowed(nRow) ); aContextMenu.CheckItem( SID_TABLEDESIGN_TABED_PRIMARYKEY, IsRowSelected(GetCurRow()) && IsPrimaryKey() ); // jetzt alles, was disabled wurde, wech aContextMenu.RemoveDisabledEntries(sal_True, sal_True); if( SetDataPtr(m_nDataPos) ) pDescrWin->SaveData( pActRow->GetActFieldDescr() ); ////////////////////////////////////////////////////////////// // Alle Aktionen, die die Zeilenzahl veraendern, muessen asynchron // ausgefuehrt werden->sonst Probleme zwischen Kontextmenu u. Browser m_nDataPos = GetCurRow(); switch (aContextMenu.Execute(this, aMenuPos)) { case SID_CUT: cut(); break; case SID_COPY: copy(); break; case SID_PASTE: paste(); break; case SID_DELETE: if( nDeleteEvent ) Application::RemoveUserEvent( nDeleteEvent ); nDeleteEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedDelete) ); break; case SID_TABLEDESIGN_INSERTROWS: if( nInsNewRowsEvent ) Application::RemoveUserEvent( nInsNewRowsEvent ); nInsNewRowsEvent = Application::PostUserEvent( LINK(this, OTableEditorCtrl, DelayedInsNewRows) ); break; case SID_TABLEDESIGN_TABED_PRIMARYKEY: SetPrimaryKey( !IsPrimaryKey() ); break; default: break; } } } } break; default: OTableRowView::Command(rEvt); } } //------------------------------------------------------------------------------ IMPL_LINK( OTableEditorCtrl, DelayedCut, void*, /*EMPTYTAG*/ ) { nCutEvent = 0; OTableRowView::cut(); return 0; } //------------------------------------------------------------------------------ IMPL_LINK( OTableEditorCtrl, DelayedPaste, void*, /*EMPTYTAG*/ ) { nPasteEvent = 0; sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition(); if ( !GetView()->getController().getTable().is() ) nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : GetCurRow(); if (!IsInsertNewAllowed(nPastePosition)) { // kein Einfuegen erlaubt, sondern nur anhaengen, also testen, ob hinter der PastePosition noch // belegte Zeilen erscheinen sal_Int32 nFreeFromPos; // ab da nur freie Zeilen ::std::vector< ::boost::shared_ptr >::reverse_iterator aIter = m_pRowList->rbegin(); for(nFreeFromPos = m_pRowList->size(); aIter != m_pRowList->rend() && (!(*aIter) || !(*aIter)->GetActFieldDescr() || !(*aIter)->GetActFieldDescr()->GetName().getLength()); --nFreeFromPos, ++aIter) ; if (nPastePosition < nFreeFromPos) // es gibt mindestens eine belegte hinter PastePosition -> ganz nach hinten nPastePosition = nFreeFromPos; } OTableRowView::Paste( nPastePosition ); SetNoSelection(); GoToRow( nPastePosition ); return 0; } //------------------------------------------------------------------------------ IMPL_LINK( OTableEditorCtrl, DelayedDelete, void*, /*EMPTYTAG*/ ) { nDeleteEvent = 0; DeleteRows(); return 0; } //------------------------------------------------------------------------------ IMPL_LINK( OTableEditorCtrl, DelayedInsNewRows, void*, /*EMPTYTAG*/ ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); nInsNewRowsEvent = 0; sal_Int32 nPastePosition = GetView()->getController().getFirstEmptyRowPosition(); if ( !GetView()->getController().getTable().is() ) nPastePosition = GetSelectRowCount() ? FirstSelectedRow() : m_nDataPos; InsertNewRows( nPastePosition ); SetNoSelection(); GoToRow( nPastePosition ); return 0; } // ----------------------------------------------------------------------------- void OTableEditorCtrl::AdjustFieldDescription(OFieldDescription* _pFieldDesc, MultiSelection& _rMultiSel, sal_Int32 _nPos, sal_Bool _bSet, sal_Bool _bPrimaryKey) { _pFieldDesc->SetPrimaryKey( _bPrimaryKey ); if(!_bSet && _pFieldDesc->getTypeInfo()->bNullable) { _pFieldDesc->SetIsNullable(ColumnValue::NO_NULLS); _pFieldDesc->SetControlDefault(Any()); } // if(!_bSet && _pFieldDesc->getTypeInfo()->bNullable) if ( _pFieldDesc->IsAutoIncrement() && !_bPrimaryKey ) { OTableController& rController = GetView()->getController(); if ( rController.isAutoIncrementPrimaryKey() ) { _pFieldDesc->SetAutoIncrement(false); } } ////////////////////////////////////////////////////////////////////// // update field description pDescrWin->DisplayData(_pFieldDesc); _rMultiSel.Insert( _nPos ); _rMultiSel.Select( _nPos ); } //------------------------------------------------------------------------------ void OTableEditorCtrl::SetPrimaryKey( sal_Bool bSet ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Evtl. vorhandene Primary Keys loeschen MultiSelection aDeletedPrimKeys; aDeletedPrimKeys.SetTotalRange( Range(0,GetRowCount()) ); long nIndex = 0; ::std::vector< ::boost::shared_ptr >::const_iterator aIter = m_pRowList->begin(); ::std::vector< ::boost::shared_ptr >::const_iterator aEnd = m_pRowList->end(); for(sal_Int32 nRow = 0;aIter != aEnd;++aIter,++nRow) { OFieldDescription* pFieldDescr = (*aIter)->GetActFieldDescr(); if( pFieldDescr && (*aIter)->IsPrimaryKey() && (!bSet || !IsRowSelected(nRow)) ) { AdjustFieldDescription(pFieldDescr,aDeletedPrimKeys,nRow,bSet,sal_False); } } ////////////////////////////////////////////////////////////////////// // Die Primary Keys der markierten Zeilen setzen MultiSelection aInsertedPrimKeys; aInsertedPrimKeys.SetTotalRange( Range(0,GetRowCount()) ); if( bSet ) { nIndex = FirstSelectedRow(); while( nIndex >= 0 && nIndex < static_cast(m_pRowList->size()) ) { ////////////////////////////////////////////////////////////////////// // Key setzen ::boost::shared_ptr pRow = (*m_pRowList)[nIndex]; OFieldDescription* pFieldDescr = pRow->GetActFieldDescr(); if(pFieldDescr) AdjustFieldDescription(pFieldDescr,aInsertedPrimKeys,nIndex,sal_False,sal_True); nIndex = NextSelectedRow(); } } GetUndoManager()->AddUndoAction( new OPrimKeyUndoAct(this, aDeletedPrimKeys, aInsertedPrimKeys) ); ////////////////////////////////////////////////////////////////////// // Handle-Spalte invalidieren InvalidateHandleColumn(); ////////////////////////////////////////////////////////////////////// // Das ModifyFlag der TableDocSh setzen GetView()->getController().setModified( sal_True ); InvalidateFeatures(); } //------------------------------------------------------------------------------ sal_Bool OTableEditorCtrl::IsPrimaryKey() { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Gehoeren alle markierten Felder zu einem Primary Key ? long nPrimaryKeys = 0; ::std::vector< ::boost::shared_ptr >::const_iterator aIter = m_pRowList->begin(); ::std::vector< ::boost::shared_ptr >::const_iterator aEnd = m_pRowList->end(); for(sal_Int32 nRow=0;aIter != aEnd;++aIter,++nRow) { if( IsRowSelected(nRow) && !(*aIter)->IsPrimaryKey() ) return sal_False; if( (*aIter)->IsPrimaryKey() ) ++nPrimaryKeys; } ////////////////////////////////////////////////////////////////////// // Gibt es unselektierte Felder, die noch zu dem Key gehoeren ? return GetSelectRowCount() == nPrimaryKeys; } //------------------------------------------------------------------------------ void OTableEditorCtrl::SwitchType( const TOTypeInfoSP& _pType ) { DBG_CHKTHIS(OTableEditorCtrl,NULL); ////////////////////////////////////////////////////////////////////// // Wenn noch kein Feldname vergeben wurde long nRow(GetCurRow()); OFieldDescription* pActFieldDescr = GetFieldDescr( nRow ); if( pActFieldDescr ) ////////////////////////////////////////////////////////////////////// // Alte Beschreibung speichern pDescrWin->SaveData( pActFieldDescr ); if ( nRow < 0 || nRow > static_cast(m_pRowList->size()) ) return; ////////////////////////////////////////////////////////////////////// // Neue Beschreibung darstellen ::boost::shared_ptr pRow = (*m_pRowList)[nRow]; pRow->SetFieldType( _pType, sal_True ); if ( _pType.get() ) { const sal_uInt16 nCurrentlySelected = pTypeCell->GetSelectEntryPos(); if ( ( LISTBOX_ENTRY_NOTFOUND == nCurrentlySelected ) || ( GetView()->getController().getTypeInfo( nCurrentlySelected ) != _pType ) ) { USHORT nEntryPos = 0; const OTypeInfoMap* pTypeInfo = GetView()->getController().getTypeInfo(); OTypeInfoMap::const_iterator aIter = pTypeInfo->begin(); OTypeInfoMap::const_iterator aEnd = pTypeInfo->end(); for(;aIter != aEnd;++aIter,++nEntryPos) { if(aIter->second == _pType) break; } if (nEntryPos < pTypeCell->GetEntryCount()) pTypeCell->SelectEntryPos( nEntryPos ); } } pActFieldDescr = pRow->GetActFieldDescr(); if (pActFieldDescr != NULL && !pActFieldDescr->GetFormatKey()) { sal_Int32 nFormatKey = ::dbtools::getDefaultNumberFormat( pActFieldDescr->GetType(), pActFieldDescr->GetScale(), pActFieldDescr->IsCurrency(), Reference< XNumberFormatTypes>(GetView()->getController().getNumberFormatter()->getNumberFormatsSupplier()->getNumberFormats(),UNO_QUERY), GetView()->getLocale()); pActFieldDescr->SetFormatKey(nFormatKey); } pDescrWin->DisplayData( pActFieldDescr ); } // ----------------------------------------------------------------------------- OTableDesignView* OTableEditorCtrl::GetView() const { return static_cast(GetParent()->GetParent()); } // ----------------------------------------------------------------------------- void OTableEditorCtrl::DeactivateCell(sal_Bool bUpdate) { OTableRowView::DeactivateCell(bUpdate); // now we have to deactivate the field description long nRow(GetCurRow()); if (pDescrWin) pDescrWin->SetReadOnly(bReadOnly || !SetDataPtr(nRow) || GetActRow()->IsReadOnly()); } //------------------------------------------------------------------------------ long OTableEditorCtrl::PreNotify( NotifyEvent& rNEvt ) { if (rNEvt.GetType() == EVENT_GETFOCUS) { if( pDescrCell && pDescrCell->HasChildPathFocus() ) m_eChildFocus = DESCRIPTION; else if(pNameCell && pNameCell->HasChildPathFocus() ) m_eChildFocus = NAME; else m_eChildFocus = ROW; } return OTableRowView::PreNotify(rNEvt); } // -----------------------------------------------------------------------------