| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svx.hxx" |
| |
| #include "svx/dbexch.hrc" |
| #include "svx/fmgridif.hxx" |
| #include "fmitems.hxx" |
| #include "fmprop.hrc" |
| #include "svx/fmtools.hxx" |
| #include "svx/fmresids.hrc" |
| #include "fmservs.hxx" |
| #include "fmurl.hxx" |
| #include "formcontrolfactory.hxx" |
| #include "gridcell.hxx" |
| #include "gridcols.hxx" |
| #include "svx/dbaexchange.hxx" |
| #include "svx/dialmgr.hxx" |
| #include "svx/dialogs.hrc" |
| #include "svx/fmgridcl.hxx" |
| #include "svx/svxdlg.hxx" |
| #include "svx/svxids.hrc" |
| #include "trace.hxx" |
| |
| #include <com/sun/star/form/XConfirmDeleteListener.hpp> |
| #include <com/sun/star/form/XFormComponent.hpp> |
| #include <com/sun/star/form/XGridColumnFactory.hpp> |
| #include <com/sun/star/io/XPersistObject.hpp> |
| #include <com/sun/star/sdb/CommandType.hpp> |
| #include <com/sun/star/sdb/RowChangeAction.hpp> |
| #include <com/sun/star/sdb/XQueriesSupplier.hpp> |
| #include <com/sun/star/sdbc/DataType.hpp> |
| #include <com/sun/star/sdbc/XPreparedStatement.hpp> |
| #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> |
| #include <com/sun/star/sdbcx/XDeleteRows.hpp> |
| #include <com/sun/star/sdbcx/XTablesSupplier.hpp> |
| #include <com/sun/star/uno/XNamingService.hpp> |
| #include <com/sun/star/util/XNumberFormats.hpp> |
| #include <com/sun/star/util/XNumberFormatsSupplier.hpp> |
| #include <com/sun/star/util/XURLTransformer.hpp> |
| #include <com/sun/star/view/XSelectionSupplier.hpp> |
| |
| #ifndef _SVSTDARR_STRINGSDTOR |
| #define _SVSTDARR_STRINGSDTOR |
| #define _SVSTDARR_ULONGS |
| #include <svl/svstdarr.hxx> |
| #endif |
| |
| #include <comphelper/extract.hxx> |
| #include <comphelper/numbers.hxx> |
| #include <comphelper/processfactory.hxx> |
| #include <comphelper/property.hxx> |
| #include <connectivity/dbtools.hxx> |
| #include <sfx2/dispatch.hxx> |
| #include <sfx2/viewfrm.hxx> |
| #include <svl/eitem.hxx> |
| #include <svtools/fmtfield.hxx> |
| #include <svl/numuno.hxx> |
| #include <tools/multisel.hxx> |
| #include <tools/shl.hxx> |
| #include <tools/diagnose_ex.h> |
| #include <vcl/help.hxx> |
| #include <vcl/image.hxx> |
| #include <vcl/longcurr.hxx> |
| #include <vcl/menu.hxx> |
| |
| #include <math.h> |
| |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::view; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::sdbcx; |
| using namespace ::com::sun::star::sdbc; |
| using namespace ::com::sun::star::sdb; |
| using namespace ::com::sun::star::form; |
| using namespace ::com::sun::star::util; |
| using namespace ::com::sun::star::container; |
| using namespace ::cppu; |
| using namespace ::svxform; |
| using namespace ::svx; |
| |
| //============================================================================== |
| //------------------------------------------------------------------------------ |
| ::rtl::OUString FieldServiceFromId(sal_Int32 nID) |
| { |
| switch (nID) |
| { |
| case SID_FM_EDIT : return FM_COL_TEXTFIELD; |
| case SID_FM_COMBOBOX : return FM_COL_COMBOBOX; |
| case SID_FM_LISTBOX : return FM_COL_LISTBOX; |
| case SID_FM_CHECKBOX : return FM_COL_CHECKBOX; |
| case SID_FM_DATEFIELD : return FM_COL_DATEFIELD; |
| case SID_FM_TIMEFIELD : return FM_COL_TIMEFIELD; |
| case SID_FM_NUMERICFIELD : return FM_COL_NUMERICFIELD; |
| case SID_FM_CURRENCYFIELD : return FM_COL_CURRENCYFIELD; |
| case SID_FM_PATTERNFIELD : return FM_COL_PATTERNFIELD; |
| case SID_FM_FORMATTEDFIELD : return FM_COL_FORMATTEDFIELD; |
| } |
| return ::rtl::OUString(); |
| } |
| |
| //============================================================================== |
| struct FmGridHeaderData |
| { |
| ODataAccessDescriptor aDropData; |
| Point aDropPosPixel; |
| sal_Int8 nDropAction; |
| Reference< XInterface > xDroppedStatement; |
| Reference< XInterface > xDroppedResultSet; |
| }; |
| |
| //============================================================================== |
| //------------------------------------------------------------------------------ |
| const sal_Int16 nChangeTypeOffset = 1000; |
| void SetMenuItem(const ImageList& rList, sal_uInt16 nID, Menu* pMenu, Menu& rNewMenu, sal_Bool bDesignMode = sal_True, sal_Int16 nOffset = nChangeTypeOffset) |
| { |
| pMenu->SetItemImage(nID, rList.GetImage(nID)); |
| pMenu->EnableItem(nID, bDesignMode); |
| rNewMenu.InsertItem(nID + nOffset, pMenu->GetItemText(nID)); |
| rNewMenu.SetItemImage(nID + nOffset, rList.GetImage(nID)); |
| rNewMenu.SetHelpId(nID + nOffset, pMenu->GetHelpId(nID)); |
| rNewMenu.EnableItem(nID + nOffset, bDesignMode); |
| } |
| |
| //------------------------------------------------------------------------------ |
| FmGridHeader::FmGridHeader( BrowseBox* pParent, WinBits nWinBits) |
| :EditBrowserHeader(pParent, nWinBits) |
| ,DropTargetHelper(this) |
| ,m_pImpl(new FmGridHeaderData) |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| FmGridHeader::~FmGridHeader() |
| { |
| delete m_pImpl; |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const |
| { |
| return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId); |
| } |
| //--------------------------------------------------------------------------------------- |
| void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId) |
| { |
| sal_uInt16 nPos = GetModelColumnPos(nColumnId); |
| Reference< XIndexAccess > xColumns(((FmGridControl*)GetParent())->GetPeer()->getColumns(), UNO_QUERY); |
| if ( nPos < xColumns->getCount() ) |
| { |
| Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); |
| if ( xSelSupplier.is() ) |
| { |
| Reference< XPropertySet > xColumn; |
| xColumns->getByIndex(nPos) >>= xColumn; |
| xSelSupplier->select(makeAny(xColumn)); |
| } |
| } |
| } |
| //------------------------------------------------------------------------------ |
| void FmGridHeader::Select() |
| { |
| EditBrowserHeader::Select(); |
| notifyColumnSelect(GetCurItemId()); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridHeader::RequestHelp( const HelpEvent& rHEvt ) |
| { |
| sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); |
| if ( nItemId ) |
| { |
| if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) ) |
| { |
| Rectangle aItemRect = GetItemRect( nItemId ); |
| Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); |
| aItemRect.Left() = aPt.X(); |
| aItemRect.Top() = aPt.Y(); |
| aPt = OutputToScreenPixel( aItemRect.BottomRight() ); |
| aItemRect.Right() = aPt.X(); |
| aItemRect.Bottom() = aPt.Y(); |
| |
| sal_uInt16 nPos = GetModelColumnPos(nItemId); |
| Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); |
| try |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xColumn(xColumns->getByIndex(nPos),UNO_QUERY); |
| ::rtl::OUString aHelpText; |
| xColumn->getPropertyValue(FM_PROP_HELPTEXT) >>= aHelpText; |
| if ( !aHelpText.getLength() ) |
| xColumn->getPropertyValue(FM_PROP_DESCRIPTION) >>= aHelpText; |
| if ( aHelpText.getLength() ) |
| { |
| if ( rHEvt.GetMode() & HELPMODE_BALLOON ) |
| Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText ); |
| else |
| Help::ShowQuickHelp( this, aItemRect, aHelpText ); |
| return; |
| } |
| } |
| catch(Exception&) |
| { |
| return; |
| } |
| } |
| } |
| EditBrowserHeader::RequestHelp( rHEvt ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Int8 FmGridHeader::AcceptDrop( const AcceptDropEvent& rEvt ) |
| { |
| // drop allowed in design mode only |
| if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode()) |
| return DND_ACTION_NONE; |
| |
| // search for recognized formats |
| const DataFlavorExVector& rFlavors = GetDataFlavorExVector(); |
| if (OColumnTransferable::canExtractColumnDescriptor(rFlavors, CTF_COLUMN_DESCRIPTOR | CTF_FIELD_DESCRIPTOR)) |
| return rEvt.mnAction; |
| |
| return DND_ACTION_NONE; |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Int8 FmGridHeader::ExecuteDrop( const ExecuteDropEvent& _rEvt ) |
| { |
| if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode()) |
| return DND_ACTION_NONE; |
| |
| TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable); |
| |
| // check the formats |
| sal_Bool bColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR); |
| sal_Bool bFieldDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR); |
| if (!bColumnDescriptor && !bFieldDescriptor) |
| { |
| DBG_ERROR("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!"); |
| return DND_ACTION_NONE; |
| } |
| |
| // extract the descriptor |
| ::rtl::OUString sDatasouce, sCommand, sFieldName,sDatabaseLocation,sConnnectionResource; |
| sal_Int32 nCommandType = CommandType::COMMAND; |
| Reference< XPreparedStatement > xStatement; |
| Reference< XResultSet > xResultSet; |
| Reference< XPropertySet > xField; |
| Reference< XConnection > xConnection; |
| |
| ODataAccessDescriptor aColumn = OColumnTransferable::extractColumnDescriptor(aDroppedData); |
| if (aColumn.has(daDataSource)) aColumn[daDataSource] >>= sDatasouce; |
| if (aColumn.has(daDatabaseLocation)) aColumn[daDatabaseLocation] >>= sDatabaseLocation; |
| if (aColumn.has(daConnectionResource)) aColumn[daConnectionResource] >>= sConnnectionResource; |
| if (aColumn.has(daCommand)) aColumn[daCommand] >>= sCommand; |
| if (aColumn.has(daCommandType)) aColumn[daCommandType] >>= nCommandType; |
| if (aColumn.has(daColumnName)) aColumn[daColumnName] >>= sFieldName; |
| if (aColumn.has(daColumnObject))aColumn[daColumnObject] >>= xField; |
| if (aColumn.has(daConnection)) aColumn[daConnection] >>= xConnection; |
| |
| if ( !sFieldName.getLength() |
| || !sCommand.getLength() |
| || ( !sDatasouce.getLength() |
| && !sDatabaseLocation.getLength() |
| && !xConnection.is() |
| ) |
| ) |
| { |
| DBG_ERROR( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" ); |
| return DND_ACTION_NONE; |
| } |
| |
| try |
| { |
| // need a connection |
| if (!xConnection.is()) |
| { // the transferable did not contain the connection -> build an own one |
| try |
| { |
| ::rtl::OUString sSignificantSource( sDatasouce.getLength() ? sDatasouce : sDatabaseLocation ); |
| xConnection = OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource, ::rtl::OUString(),::rtl::OUString(),static_cast<FmGridControl*>(GetParent())->getServiceManager()); |
| } |
| catch(NoSuchElementException&) |
| { // allowed, means sDatasouce isn't a valid data source name .... |
| } |
| catch(Exception&) |
| { |
| DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !"); |
| } |
| |
| if (!xConnection.is()) |
| { |
| DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !"); |
| return DND_ACTION_NONE; |
| } |
| } |
| |
| // try to obtain the column object |
| if (!xField.is()) |
| { |
| #ifdef DBG_UTIL |
| Reference< XServiceInfo > xServiceInfo(xConnection, UNO_QUERY); |
| DBG_ASSERT(xServiceInfo.is() && xServiceInfo->supportsService(SRV_SDB_CONNECTION), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)"); |
| #endif |
| |
| Reference< XNameAccess > xFields; |
| switch (nCommandType) |
| { |
| case CommandType::TABLE: |
| { |
| Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY); |
| Reference< XColumnsSupplier > xSupplyColumns; |
| xSupplyTables->getTables()->getByName(sCommand) >>= xSupplyColumns; |
| xFields = xSupplyColumns->getColumns(); |
| } |
| break; |
| case CommandType::QUERY: |
| { |
| Reference< XQueriesSupplier > xSupplyQueries(xConnection, UNO_QUERY); |
| Reference< XColumnsSupplier > xSupplyColumns; |
| xSupplyQueries->getQueries()->getByName(sCommand) >>= xSupplyColumns; |
| xFields = xSupplyColumns->getColumns(); |
| } |
| break; |
| default: |
| { |
| xStatement = xConnection->prepareStatement(sCommand); |
| // not interested in any results |
| |
| Reference< XPropertySet > xStatProps(xStatement,UNO_QUERY); |
| xStatProps->setPropertyValue(rtl::OUString::createFromAscii("MaxRows"), makeAny(sal_Int32(0))); |
| |
| xResultSet = xStatement->executeQuery(); |
| Reference< XColumnsSupplier > xSupplyCols(xResultSet, UNO_QUERY); |
| if (xSupplyCols.is()) |
| xFields = xSupplyCols->getColumns(); |
| } |
| } |
| |
| if (xFields.is() && xFields->hasByName(sFieldName)) |
| xFields->getByName(sFieldName) >>= xField; |
| |
| if (!xField.is()) |
| { |
| ::comphelper::disposeComponent(xStatement); |
| return DND_ACTION_NONE; |
| } |
| } |
| |
| // do the drop asynchronously |
| // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu) |
| m_pImpl->aDropData = aColumn; |
| m_pImpl->aDropData[daConnection] <<= xConnection; |
| m_pImpl->aDropData[daColumnObject] <<= xField; |
| |
| m_pImpl->nDropAction = _rEvt.mnAction; |
| m_pImpl->aDropPosPixel = _rEvt.maPosPixel; |
| m_pImpl->xDroppedStatement = xStatement; |
| m_pImpl->xDroppedResultSet = xResultSet; |
| |
| PostUserEvent(LINK(this, FmGridHeader, OnAsyncExecuteDrop)); |
| } |
| catch (Exception&) |
| { |
| DBG_ERROR("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !"); |
| ::comphelper::disposeComponent(xStatement); |
| return sal_False; |
| } |
| |
| return DND_ACTION_LINK; |
| } |
| |
| //------------------------------------------------------------------------------ |
| IMPL_LINK( FmGridHeader, OnAsyncExecuteDrop, void*, /*NOTINTERESTEDIN*/ ) |
| { |
| ::rtl::OUString sCommand, sFieldName,sURL; |
| sal_Int32 nCommandType = CommandType::COMMAND; |
| Reference< XPropertySet > xField; |
| Reference< XConnection > xConnection; |
| |
| ::rtl::OUString sDatasouce = m_pImpl->aDropData.getDataSource(); |
| if ( !sDatasouce.getLength() && m_pImpl->aDropData.has(daConnectionResource) ) |
| m_pImpl->aDropData[daConnectionResource] >>= sURL; |
| m_pImpl->aDropData[daCommand] >>= sCommand; |
| m_pImpl->aDropData[daCommandType] >>= nCommandType; |
| m_pImpl->aDropData[daColumnName] >>= sFieldName; |
| m_pImpl->aDropData[daConnection] >>= xConnection; |
| m_pImpl->aDropData[daColumnObject] >>= xField; |
| |
| try |
| { |
| // need number formats |
| Reference< XNumberFormatsSupplier > xSupplier = OStaticDataAccessTools().getNumberFormats(xConnection, sal_True); |
| Reference< XNumberFormats > xNumberFormats; |
| if (xSupplier.is()) |
| xNumberFormats = xSupplier->getNumberFormats(); |
| if (!xNumberFormats.is()) |
| { |
| ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); |
| ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); |
| return 0L; |
| } |
| |
| // Vom Feld werden nun zwei Informationen benoetigt: |
| // a.) Name des Feldes fuer Label und ControlSource |
| // b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll |
| sal_Int32 nDataType = 0; |
| xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nDataType; |
| // diese Datentypen koennen im Gridcontrol nicht verarbeitet werden |
| switch (nDataType) |
| { |
| case DataType::BLOB: |
| case DataType::LONGVARBINARY: |
| case DataType::BINARY: |
| case DataType::VARBINARY: |
| case DataType::OTHER: |
| ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); |
| ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); |
| return 0L; |
| } |
| |
| // Erstellen der Column |
| Reference< XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); |
| Reference< XGridColumnFactory > xFactory(xCols, UNO_QUERY); |
| |
| Point aPos = OutputToScreenPixel(m_pImpl->aDropPosPixel); |
| sal_uInt16 nColId = GetItemId(m_pImpl->aDropPosPixel); |
| // EinfuegePosition, immer vor der aktuellen Spalte |
| sal_uInt16 nPos = GetModelColumnPos(nColId); |
| Reference< XPropertySet > xCol, xSecondCol; |
| |
| // erzeugen der Column in abhaengigkeit vom type, default textfeld |
| SvULongs aPossibleTypes; |
| switch (nDataType) |
| { |
| case DataType::BIT: |
| case DataType::BOOLEAN: |
| aPossibleTypes.Insert(SID_FM_CHECKBOX, aPossibleTypes.Count()); |
| break; |
| case DataType::TINYINT: |
| case DataType::SMALLINT: |
| case DataType::INTEGER: |
| aPossibleTypes.Insert(SID_FM_NUMERICFIELD, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); |
| break; |
| case DataType::REAL: |
| case DataType::DOUBLE: |
| case DataType::NUMERIC: |
| case DataType::DECIMAL: |
| aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_NUMERICFIELD, aPossibleTypes.Count()); |
| break; |
| case DataType::TIMESTAMP: |
| aPossibleTypes.Insert(SID_FM_TWOFIELDS_DATE_N_TIME, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); |
| break; |
| case DataType::DATE: |
| aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); |
| break; |
| case DataType::TIME: |
| aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); |
| break; |
| case DataType::CHAR: |
| case DataType::VARCHAR: |
| case DataType::LONGVARCHAR: |
| default: |
| aPossibleTypes.Insert(SID_FM_EDIT, aPossibleTypes.Count()); |
| aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); |
| break; |
| } |
| // if it's a currency field, a a "currency field" option |
| try |
| { |
| if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField) |
| && ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY))) |
| aPossibleTypes.Insert(SID_FM_CURRENCYFIELD, 0); |
| } |
| catch(Exception&) |
| { |
| DBG_ERROR("FmGridHeader::ExecuteDrop: Exception occured!"); |
| } |
| |
| sal_Int32 nPreferedType = -1; |
| sal_Bool bDateNTimeCol = sal_False; |
| if (aPossibleTypes.Count() != 0) |
| { |
| nPreferedType = aPossibleTypes[0]; |
| if ((m_pImpl->nDropAction == DND_ACTION_LINK) && (aPossibleTypes.Count() > 1)) |
| { |
| ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) ); |
| |
| PopupMenu aInsertMenu(SVX_RES(RID_SVXMNU_COLS)); |
| PopupMenu aTypeMenu; |
| PopupMenu* pMenu = aInsertMenu.GetPopupMenu(SID_FM_INSERTCOL); |
| for (sal_uInt32 i=0; i<aPossibleTypes.Count(); ++i) |
| SetMenuItem(aImageList, sal_uInt16(aPossibleTypes[(sal_uInt16)i]), pMenu, aTypeMenu, sal_True, 0); |
| nPreferedType = aTypeMenu.Execute(this, m_pImpl->aDropPosPixel); |
| } |
| |
| bDateNTimeCol = nPreferedType == SID_FM_TWOFIELDS_DATE_N_TIME; |
| sal_uInt16 nColCount = bDateNTimeCol ? 2 : 1; |
| ::rtl::OUString sFieldService; |
| while (nColCount--) |
| { |
| if (bDateNTimeCol) |
| nPreferedType = nColCount ? SID_FM_DATEFIELD : SID_FM_TIMEFIELD; |
| |
| sFieldService = FieldServiceFromId(nPreferedType); |
| Reference< XPropertySet > xThisRoundCol; |
| if ( sFieldService.getLength() ) |
| xThisRoundCol = xFactory->createColumn(sFieldService); |
| if (nColCount) |
| xSecondCol = xThisRoundCol; |
| else |
| xCol = xThisRoundCol; |
| } |
| } |
| |
| if (!xCol.is() || (bDateNTimeCol && !xSecondCol.is())) |
| { |
| ::comphelper::disposeComponent(xCol); // in case only the creation of the second column failed |
| ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); |
| ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); |
| return 0L; |
| } |
| |
| if (bDateNTimeCol) |
| { |
| String sTimePostfix( SVX_RES( RID_STR_POSTFIX_TIME ) ); |
| xCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sTimePostfix ) ) ); |
| |
| String sDatePostfix( SVX_RES( RID_STR_POSTFIX_DATE ) ); |
| xSecondCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sDatePostfix ) ) ); |
| } |
| else |
| xCol->setPropertyValue(FM_PROP_LABEL, makeAny(sFieldName)); |
| |
| FormControlFactory aControlFactory( ::comphelper::getProcessServiceFactory() ); |
| aControlFactory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xCol ); |
| aControlFactory.initializeFieldDependentProperties( xField, xCol, xNumberFormats ); |
| |
| xCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName)); |
| if ( xSecondCol.is() ) |
| xSecondCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName)); |
| |
| if (bDateNTimeCol) |
| { |
| String sRealName,sPurePostfix; |
| |
| String aPostfix[] = { |
| String( SVX_RES( RID_STR_POSTFIX_DATE ) ), |
| String( SVX_RES( RID_STR_POSTFIX_TIME ) ) |
| }; |
| |
| for ( size_t i=0; i<2; ++i ) |
| { |
| sPurePostfix = aPostfix[i]; |
| sPurePostfix.EraseLeadingChars(' '); |
| sPurePostfix.EraseLeadingChars('('); |
| sPurePostfix.EraseTrailingChars(')'); |
| sRealName = sFieldName; |
| sRealName += '_'; |
| sRealName += sPurePostfix; |
| if (i) |
| xSecondCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName))); |
| else |
| xCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName))); |
| } |
| } |
| else |
| xCol->setPropertyValue(FM_PROP_NAME, makeAny(sFieldName)); |
| |
| // jetzt einfuegen |
| Any aElement; |
| aElement <<= xCol; |
| xCols->insertByIndex(nPos, aElement); |
| |
| if (bDateNTimeCol) |
| { |
| aElement <<= xSecondCol; |
| xCols->insertByIndex(nPos == (sal_uInt16)-1 ? nPos : ++nPos, aElement); |
| } |
| |
| // ist die component::Form an die Datenbankangebunden? |
| Reference< XFormComponent > xFormCp(xCols, UNO_QUERY); |
| Reference< XPropertySet > xForm(xFormCp->getParent(), UNO_QUERY); |
| if (xForm.is()) |
| { |
| if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_DATASOURCE)).getLength()) |
| { |
| if ( sDatasouce.getLength() ) |
| xForm->setPropertyValue(FM_PROP_DATASOURCE, makeAny(sDatasouce)); |
| else |
| xForm->setPropertyValue(FM_PROP_URL, makeAny(sURL)); |
| } |
| |
| if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_COMMAND)).getLength()) |
| { |
| xForm->setPropertyValue(FM_PROP_COMMAND, makeAny(sCommand)); |
| Any aCommandType; |
| switch (nCommandType) |
| { |
| case CommandType::TABLE: |
| aCommandType <<= (sal_Int32)CommandType::TABLE; |
| break; |
| case CommandType::QUERY: |
| aCommandType <<= (sal_Int32)CommandType::QUERY; |
| break; |
| default: |
| aCommandType <<= (sal_Int32)CommandType::COMMAND; |
| xForm->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, bool2any((sal_Bool)(2 == nCommandType))); |
| break; |
| } |
| xForm->setPropertyValue(FM_PROP_COMMANDTYPE, aCommandType); |
| } |
| } |
| } |
| catch (Exception&) |
| { |
| DBG_ERROR("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !"); |
| ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); |
| ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); |
| return 0L; |
| } |
| |
| ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); |
| ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); |
| return 1L; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu) |
| { |
| sal_Bool bDesignMode = static_cast<FmGridControl*>(GetParent())->IsDesignMode(); |
| |
| Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); |
| // Aufbau des Insert Menues |
| // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND |
| if(nColId > 0) |
| { |
| sal_uInt16 nPos2 = GetModelColumnPos(nColId); |
| |
| Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); |
| Reference< ::com::sun::star::beans::XPropertySet> xColumn; |
| ::cppu::extractInterface(xColumn, xColumns->getByIndex(nPos2)); |
| Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); |
| if (xSelSupplier.is()) |
| xSelSupplier->select(makeAny(xColumn)); |
| } |
| |
| // EinfuegePosition, immer vor der aktuellen Spalte |
| sal_uInt16 nPos = GetModelColumnPos(nColId); |
| sal_Bool bMarked = nColId && static_cast<FmGridControl*>(GetParent())->isColumnMarked(nColId); |
| |
| ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) ); |
| PopupMenu* pControlMenu = new PopupMenu; |
| |
| PopupMenu* pMenu = rMenu.GetPopupMenu(SID_FM_INSERTCOL); |
| if (pMenu) |
| { |
| SetMenuItem(aImageList, SID_FM_EDIT, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_CHECKBOX, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_COMBOBOX, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_LISTBOX, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_DATEFIELD, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_TIMEFIELD, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_NUMERICFIELD, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_CURRENCYFIELD, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_PATTERNFIELD, pMenu, *pControlMenu, bDesignMode); |
| SetMenuItem(aImageList, SID_FM_FORMATTEDFIELD, pMenu, *pControlMenu, bDesignMode); |
| } |
| |
| if (pMenu && xCols.is() && nColId) |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xSet; |
| ::cppu::extractInterface(xSet, xCols->getByIndex(nPos)); |
| sal_Int16 nClassId; |
| xSet->getPropertyValue(FM_PROP_CLASSID) >>= nClassId; |
| |
| Reference< ::com::sun::star::io::XPersistObject > xServiceQuestion(xSet, UNO_QUERY); |
| sal_Int32 nColType = xServiceQuestion.is() ? getColumnTypeByModelName(xServiceQuestion->getServiceName()) : 0; |
| if (nColType == TYPE_TEXTFIELD) |
| { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD |
| // in both cases. And as columns don't have an ::com::sun::star::lang::XServiceInfo interface, we have to distinguish both |
| // types via the existence of special properties |
| Reference< ::com::sun::star::beans::XPropertySet > xProps(xSet, UNO_QUERY); |
| if (xProps.is()) |
| { |
| Reference< ::com::sun::star::beans::XPropertySetInfo > xPropsInfo = xProps->getPropertySetInfo(); |
| if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER)) |
| nColType = TYPE_FORMATTEDFIELD; |
| } |
| } |
| |
| pControlMenu->EnableItem(SID_FM_EDIT + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TEXTFIELD)); |
| pControlMenu->EnableItem(SID_FM_COMBOBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_COMBOBOX)); |
| pControlMenu->EnableItem(SID_FM_LISTBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_LISTBOX)); |
| pControlMenu->EnableItem(SID_FM_CHECKBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CHECKBOX)); |
| pControlMenu->EnableItem(SID_FM_DATEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_DATEFIELD)); |
| pControlMenu->EnableItem(SID_FM_NUMERICFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_NUMERICFIELD)); |
| pControlMenu->EnableItem(SID_FM_TIMEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TIMEFIELD)); |
| pControlMenu->EnableItem(SID_FM_CURRENCYFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CURRENCYFIELD)); |
| pControlMenu->EnableItem(SID_FM_PATTERNFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_PATTERNFIELD)); |
| pControlMenu->EnableItem(SID_FM_FORMATTEDFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_FORMATTEDFIELD)); |
| rMenu.SetPopupMenu(SID_FM_CHANGECOL, pControlMenu); |
| } |
| |
| rMenu.EnableItem(SID_FM_INSERTCOL, bDesignMode && xCols.is()); |
| rMenu.EnableItem(SID_FM_DELETECOL, bDesignMode && bMarked && xCols.is()); |
| rMenu.EnableItem(SID_FM_CHANGECOL, bDesignMode && bMarked && xCols.is()); |
| rMenu.EnableItem(SID_FM_SHOW_PROPERTY_BROWSER, bDesignMode && bMarked && xCols.is()); |
| |
| PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(SID_FM_SHOWCOLS); |
| sal_uInt16 nHiddenCols = 0; |
| if (pShowColsMenu) |
| { |
| if (xCols.is()) |
| { |
| // check for hidden cols |
| Reference< ::com::sun::star::beans::XPropertySet > xCurCol; |
| Any aHidden,aName; |
| for (sal_uInt16 i=0; i<xCols->getCount(); ++i) |
| { |
| ::cppu::extractInterface(xCurCol, xCols->getByIndex(i)); |
| DBG_ASSERT(xCurCol.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !"); |
| aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN); |
| DBG_ASSERT(aHidden.getValueType().getTypeClass() == TypeClass_BOOLEAN, |
| "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !"); |
| if (::comphelper::getBOOL(aHidden)) |
| { |
| // put the column name into the 'show col' menu |
| if (nHiddenCols < 16) |
| { // (only the first 16 items to keep the menu rather small) |
| aName = xCurCol->getPropertyValue(FM_PROP_LABEL); |
| pShowColsMenu->InsertItem(nHiddenCols + 1, ::comphelper::getString(aName), 0, nHiddenCols); |
| // the ID is arbitrary, but should be unique within the whole menu |
| } |
| ++nHiddenCols; |
| } |
| } |
| } |
| pShowColsMenu->EnableItem(SID_FM_SHOWCOLS_MORE, xCols.is() && (nHiddenCols > 16)); |
| pShowColsMenu->EnableItem(SID_FM_SHOWALLCOLS, xCols.is() && (nHiddenCols > 0)); |
| } |
| |
| // allow the 'hide column' item ? |
| sal_Bool bAllowHide = bMarked; // a column is marked |
| bAllowHide = bAllowHide || (!bDesignMode && (nPos != (sal_uInt16)-1)); // OR we are in alive mode and have hit a column |
| bAllowHide = bAllowHide && xCols.is(); // AND we have a column container |
| bAllowHide = bAllowHide && (xCols->getCount()-nHiddenCols > 1); // AND there are at least two visible columns |
| rMenu.EnableItem(SID_FM_HIDECOL, bAllowHide); |
| |
| sal_Bool bChecked = sal_False; |
| if (bMarked) |
| { |
| |
| SfxViewFrame* pCurrentFrame = SfxViewFrame::Current(); |
| SfxItemState eState = SFX_ITEM_UNKNOWN; |
| // ask the bindings of the current view frame (which should be the one we're residing in) for the state |
| if (pCurrentFrame) |
| { |
| SfxPoolItem* pItem = NULL; |
| eState = pCurrentFrame->GetBindings().QueryState(SID_FM_CTL_PROPERTIES, pItem); |
| |
| if (eState >= SFX_ITEM_AVAILABLE && pItem ) |
| { |
| bChecked = pItem->ISA(SfxBoolItem) && ((SfxBoolItem*)pItem)->GetValue(); |
| rMenu.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER,bChecked); |
| } |
| delete pItem; |
| } |
| } |
| } |
| |
| enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone }; |
| |
| //------------------------------------------------------------------------------ |
| void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult) |
| { |
| Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); |
| sal_uInt16 nPos = GetModelColumnPos(nColId); |
| |
| // remove and delet the menu we inserted in PreExecuteColumnContextMenu |
| PopupMenu* pControlMenu = rMenu.GetPopupMenu(SID_FM_CHANGECOL); |
| delete pControlMenu; |
| |
| ::rtl::OUString aFieldType; |
| sal_Bool bReplace = sal_False; |
| InspectorAction eInspectorAction = eNone; |
| Reference< XPropertySet > xColumnToInspect; |
| switch (nExecutionResult) |
| { |
| case SID_FM_DELETECOL: |
| { |
| Reference< XInterface > xCol; |
| ::cppu::extractInterface(xCol, xCols->getByIndex(nPos)); |
| xCols->removeByIndex(nPos); |
| ::comphelper::disposeComponent(xCol); |
| } break; |
| case SID_FM_SHOW_PROPERTY_BROWSER: |
| eInspectorAction = rMenu.IsItemChecked( SID_FM_SHOW_PROPERTY_BROWSER ) ? eOpenInspector : eCloseInspector; |
| xColumnToInspect.set( xCols->getByIndex( nPos ), UNO_QUERY ); |
| break; |
| case SID_FM_EDIT + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_EDIT: |
| aFieldType = FM_COL_TEXTFIELD; |
| break; |
| case SID_FM_COMBOBOX + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_COMBOBOX: |
| aFieldType = FM_COL_COMBOBOX; |
| break; |
| case SID_FM_LISTBOX + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_LISTBOX: |
| aFieldType = FM_COL_LISTBOX; |
| break; |
| case SID_FM_CHECKBOX + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_CHECKBOX: |
| aFieldType = FM_COL_CHECKBOX; |
| break; |
| case SID_FM_DATEFIELD + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_DATEFIELD: |
| aFieldType = FM_COL_DATEFIELD; |
| break; |
| case SID_FM_TIMEFIELD + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_TIMEFIELD: |
| aFieldType = FM_COL_TIMEFIELD; |
| break; |
| case SID_FM_NUMERICFIELD + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_NUMERICFIELD: |
| aFieldType = FM_COL_NUMERICFIELD; |
| break; |
| case SID_FM_CURRENCYFIELD + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_CURRENCYFIELD: |
| aFieldType = FM_COL_CURRENCYFIELD; |
| break; |
| case SID_FM_PATTERNFIELD + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_PATTERNFIELD: |
| aFieldType = FM_COL_PATTERNFIELD; |
| break; |
| case SID_FM_FORMATTEDFIELD + nChangeTypeOffset: |
| bReplace = sal_True; |
| case SID_FM_FORMATTEDFIELD: |
| aFieldType = FM_COL_FORMATTEDFIELD; |
| break; |
| case SID_FM_HIDECOL: |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xCurCol; |
| ::cppu::extractInterface(xCurCol, xCols->getByIndex(nPos)); |
| xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_True)); |
| } |
| break; |
| case SID_FM_SHOWCOLS_MORE: |
| { |
| SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); |
| if(pFact) |
| { |
| AbstractFmShowColsDialog* pDlg = pFact->CreateFmShowColsDialog(NULL); |
| DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001 |
| pDlg->SetColumns(xCols); |
| pDlg->Execute(); |
| delete pDlg; |
| } |
| |
| } |
| break; |
| case SID_FM_SHOWALLCOLS: |
| { |
| // just iterate through all the cols ... |
| Reference< ::com::sun::star::beans::XPropertySet > xCurCol; |
| for (sal_uInt16 i=0; i<xCols->getCount(); ++i) |
| { |
| ::cppu::extractInterface(xCurCol, xCols->getByIndex(i)); |
| xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False)); |
| } |
| // TODO : there must be a more clever way to do this .... |
| // with the above the view is updated after every single model update ... |
| } |
| break; |
| default: |
| if (nExecutionResult>0 && nExecutionResult<=16) |
| { // it was a "show column/<colname>" command (there are at most 16 such items) |
| // search the nExecutionResult'th hidden col |
| Reference< ::com::sun::star::beans::XPropertySet > xCurCol; |
| for (sal_uInt16 i=0; i<xCols->getCount() && nExecutionResult; ++i) |
| { |
| ::cppu::extractInterface(xCurCol, xCols->getByIndex(i)); |
| Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN); |
| if (::comphelper::getBOOL(aHidden)) |
| if (!--nExecutionResult) |
| { |
| xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False)); |
| break; |
| } |
| } |
| } |
| break; |
| } |
| |
| if ( aFieldType.getLength() ) |
| { |
| try |
| { |
| Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW ); |
| Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW ); |
| |
| if ( bReplace ) |
| { |
| // ein paar Properties hinueberretten |
| Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY ); |
| |
| OStaticDataAccessTools().TransferFormComponentProperties( |
| xReplaced, xNewCol, Application::GetSettings().GetUILocale() ); |
| |
| xCols->replaceByIndex( nPos, makeAny( xNewCol ) ); |
| ::comphelper::disposeComponent( xReplaced ); |
| |
| eInspectorAction = eUpdateInspector; |
| xColumnToInspect = xNewCol; |
| } |
| else |
| { |
| FormControlFactory factory( ::comphelper::getProcessServiceFactory() ); |
| |
| ::rtl::OUString sLabel = factory.getDefaultUniqueName_ByComponentType( |
| Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol ); |
| xNewCol->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel ) ); |
| xNewCol->setPropertyValue( FM_PROP_NAME, makeAny( sLabel ) ); |
| |
| factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol ); |
| |
| xCols->insertByIndex( nPos, makeAny( xNewCol ) ); |
| } |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| } |
| |
| SfxViewFrame* pCurrentFrame = SfxViewFrame::Current(); |
| OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" ); |
| if ( pCurrentFrame ) |
| { |
| if ( eInspectorAction == eUpdateInspector ) |
| { |
| if ( !pCurrentFrame->HasChildWindow( SID_FM_SHOW_PROPERTIES ) ) |
| eInspectorAction = eNone; |
| } |
| |
| if ( eInspectorAction != eNone ) |
| { |
| FmInterfaceItem aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER, xColumnToInspect ); |
| SfxBoolItem aShowItem( SID_FM_SHOW_PROPERTIES, eInspectorAction == eCloseInspector ? sal_False : sal_True ); |
| |
| pCurrentFrame->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON, |
| &aIFaceItem, &aShowItem, 0L ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos ) |
| { |
| // the affected col |
| sal_uInt16 nColId = GetItemId( _rPreferredPos ); |
| |
| // the menu |
| PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_COLS ) ); |
| |
| // let derivees modify the menu |
| PreExecuteColumnContextMenu( nColId, aContextMenu ); |
| aContextMenu.RemoveDisabledEntries( sal_True, sal_True ); |
| |
| // execute the menu |
| sal_uInt16 nResult = aContextMenu.Execute( this, _rPreferredPos ); |
| |
| // let derivees handle the result |
| PostExecuteColumnContextMenu( nColId, aContextMenu, nResult ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridHeader::Command(const CommandEvent& rEvt) |
| { |
| switch (rEvt.GetCommand()) |
| { |
| case COMMAND_CONTEXTMENU: |
| { |
| if (!rEvt.IsMouseEvent()) |
| return; |
| |
| triggerColumnContextMenu( rEvt.GetMousePosPixel() ); |
| } |
| break; |
| default: |
| EditBrowserHeader::Command(rEvt); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| FmGridControl::FmGridControl( |
| Reference< ::com::sun::star::lang::XMultiServiceFactory > _rxFactory, |
| Window* pParent, |
| FmXGridPeer* _pPeer, |
| WinBits nBits) |
| :DbGridControl(_rxFactory, pParent, nBits) |
| ,m_pPeer(_pPeer) |
| ,m_nCurrentSelectedColumn(-1) |
| ,m_nMarkedColumnId(BROWSER_INVALIDID) |
| ,m_bSelecting(sal_False) |
| ,m_bInColumnMove(sal_False) |
| { |
| EnableInteractiveRowHeight( ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::Command(const CommandEvent& _rEvt) |
| { |
| if ( COMMAND_CONTEXTMENU == _rEvt.GetCommand() ) |
| { |
| FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() ); |
| if ( pMyHeader && !_rEvt.IsMouseEvent() ) |
| { // context menu requested by keyboard |
| if ( 1 == GetSelectColumnCount() || IsDesignMode() ) |
| { |
| sal_uInt16 nSelId = GetColumnId( |
| sal::static_int_cast< sal_uInt16 >( FirstSelectedColumn() ) ); |
| ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, sal_False ) ); |
| |
| Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) ); |
| pMyHeader->triggerColumnContextMenu( aRelativePos, FmGridHeader::AccessControl() ); |
| |
| // handled |
| return; |
| } |
| } |
| } |
| |
| DbGridControl::Command( _rEvt ); |
| } |
| |
| // ::com::sun::star::beans::XPropertyChangeListener |
| //------------------------------------------------------------------------------ |
| void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) |
| { |
| if (evt.PropertyName == FM_PROP_ROWCOUNT) |
| { |
| // if we're not in the main thread call AdjustRows asynchronously |
| implAdjustInSolarThread(sal_True); |
| return; |
| } |
| |
| const DbGridRowRef& xRow = GetCurrentRow(); |
| // waehrend Positionierung wird kein abgleich der Properties vorgenommen |
| Reference<XPropertySet> xSet(evt.Source,UNO_QUERY); |
| if (xRow.Is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark()))) |
| { |
| if (evt.PropertyName == FM_PROP_ISMODIFIED) |
| { |
| // modified or clean ? |
| GridRowStatus eStatus = ::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN; |
| if (eStatus != xRow->GetStatus()) |
| { |
| xRow->SetStatus(eStatus); |
| vos::OGuard aGuard( Application::GetSolarMutex() ); |
| RowModified(GetCurrentPos()); |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::SetDesignMode(sal_Bool bMode) |
| { |
| sal_Bool bOldMode = IsDesignMode(); |
| DbGridControl::SetDesignMode(bMode); |
| if (bOldMode != bMode) |
| { |
| if (!bMode) |
| { |
| // selection aufheben |
| markColumn(USHRT_MAX); |
| } |
| else |
| { |
| Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns()); |
| Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); |
| if (xSelSupplier.is()) |
| { |
| Any aSelection = xSelSupplier->getSelection(); |
| Reference< ::com::sun::star::beans::XPropertySet > xColumn; |
| if (aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE) |
| ::cppu::extractInterface(xColumn, aSelection); |
| Reference< XInterface > xCurrent; |
| for (sal_uInt16 i=0; i<xColumns->getCount(); ++i) |
| { |
| ::cppu::extractInterface(xCurrent, xColumns->getByIndex(i)); |
| if (xCurrent == xColumn) |
| { |
| markColumn(GetColumnIdFromModelPos(i)); |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::DeleteSelectedRows() |
| { |
| if (!m_pSeekCursor) |
| return; |
| |
| // how many rows are selected? |
| sal_Int32 nSelectedRows = GetSelectRowCount(); |
| |
| // the current line should be deleted but it is currently in edit mode |
| if ( IsCurrentAppending() ) |
| return; |
| // is the insert row selected |
| if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1)) |
| nSelectedRows -= 1; |
| |
| // nothing to do |
| if (nSelectedRows <= 0) |
| return; |
| |
| // try to confirm the delete |
| Reference< ::com::sun::star::frame::XDispatchProvider > xDispatcher = (::com::sun::star::frame::XDispatchProvider*)GetPeer(); |
| if (xDispatcher.is()) |
| { |
| ::com::sun::star::util::URL aUrl; |
| aUrl.Complete = FMURL_CONFIRM_DELETION; |
| // #100312# ------------ |
| Reference< ::com::sun::star::util::XURLTransformer > xTransformer( |
| ::comphelper::getProcessServiceFactory()->createInstance( |
| ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY); |
| if( xTransformer.is() ) |
| xTransformer->parseStrict( aUrl ); |
| |
| Reference< ::com::sun::star::frame::XDispatch > xDispatch = xDispatcher->queryDispatch(aUrl, rtl::OUString(), 0); |
| Reference< ::com::sun::star::form::XConfirmDeleteListener > xConfirm(xDispatch, UNO_QUERY); |
| if (xConfirm.is()) |
| { |
| ::com::sun::star::sdb::RowChangeEvent aEvent; |
| aEvent.Source = (Reference< XInterface > )(*getDataSource()); |
| aEvent.Rows = nSelectedRows; |
| aEvent.Action = ::com::sun::star::sdb::RowChangeAction::DELETE; |
| if (!xConfirm->confirmDelete(aEvent)) |
| return; |
| } |
| } |
| |
| const MultiSelection* pRowSelection = GetSelection(); |
| if ( pRowSelection && pRowSelection->IsAllSelected() ) |
| { |
| BeginCursorAction(); |
| CursorWrapper* pCursor = getDataSource(); |
| Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*pCursor, UNO_QUERY); |
| try |
| { |
| pCursor->beforeFirst(); |
| while( pCursor->next() ) |
| xUpdateCursor->deleteRow(); |
| |
| SetUpdateMode(sal_False); |
| SetNoSelection(); |
| |
| xUpdateCursor->moveToInsertRow(); |
| } |
| catch(const Exception&) |
| { |
| OSL_ENSURE(0,"Exception caught while deleting rows!"); |
| } |
| // An den DatenCursor anpassen |
| AdjustDataSource(sal_True); |
| EndCursorAction(); |
| SetUpdateMode(sal_True); |
| } |
| else |
| { |
| Reference< ::com::sun::star::sdbcx::XDeleteRows > xDeleteThem((Reference< XInterface >)*getDataSource(), UNO_QUERY); |
| |
| // colect the bookmarks of the selected rows |
| Sequence < Any> aBookmarks = getSelectionBookmarks(); |
| |
| // determine the next row to position after deletion |
| Any aBookmark; |
| sal_Bool bNewPos = sal_False; |
| // if the current row isn't selected we take the row as row after deletion |
| OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" ); |
| // crash reports suggest it can happen we don't have a current row - how? |
| // #154303# / 2008-04-23 / frank.schoenheit@sun.com |
| if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() ) |
| { |
| aBookmark = GetCurrentRow()->GetBookmark(); |
| bNewPos = sal_True; |
| } |
| else |
| { |
| // we look for the first row after the selected block for selection |
| long nIdx = LastSelectedRow() + 1; |
| if (nIdx < GetRowCount() - 1) |
| { |
| // there is a next row to position on |
| if (SeekCursor(nIdx)) |
| { |
| GetSeekRow()->SetState(m_pSeekCursor, sal_True); |
| |
| bNewPos = sal_True; |
| // if it's not the row for inserting we keep the bookmark |
| if (!IsInsertionRow(nIdx)) |
| aBookmark = m_pSeekCursor->getBookmark(); |
| } |
| } |
| else |
| { |
| // we look for the first row before the selected block for selection after deletion |
| nIdx = FirstSelectedRow() - 1; |
| if (nIdx >= 0 && SeekCursor(nIdx)) |
| { |
| GetSeekRow()->SetState(m_pSeekCursor, sal_True); |
| |
| bNewPos = sal_True; |
| aBookmark = m_pSeekCursor->getBookmark(); |
| } |
| } |
| } |
| |
| // Sind alle Zeilen Selectiert |
| // Zweite bedingung falls keine einguegeZeile existiert |
| sal_Bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows; |
| |
| BeginCursorAction(); |
| |
| // now delete the row |
| Sequence <sal_Int32> aDeletedRows; |
| SetUpdateMode( sal_False ); |
| try |
| { |
| aDeletedRows = xDeleteThem->deleteRows(aBookmarks); |
| } |
| catch(SQLException&) |
| { |
| } |
| SetUpdateMode( sal_True ); |
| |
| // how many rows are deleted? |
| sal_Int32 nDeletedRows = 0; |
| const sal_Int32* pSuccess = aDeletedRows.getConstArray(); |
| for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++) |
| { |
| if (pSuccess[i]) |
| ++nDeletedRows; |
| } |
| |
| // sind Zeilen geloescht worden? |
| if (nDeletedRows) |
| { |
| SetUpdateMode(sal_False); |
| SetNoSelection(); |
| try |
| { |
| // did we delete all the rows than try to move to the next possible row |
| if (nDeletedRows == aDeletedRows.getLength()) |
| { |
| // there exists a new position to move on |
| if (bNewPos) |
| { |
| if (aBookmark.hasValue()) |
| getDataSource()->moveToBookmark(aBookmark); |
| // no valid bookmark so move to the insert row |
| else |
| { |
| Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY); |
| xUpdateCursor->moveToInsertRow(); |
| } |
| } |
| else |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xSet((Reference< XInterface >)*m_pDataCursor, UNO_QUERY); |
| |
| sal_Int32 nRecordCount(0); |
| xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount; |
| if ( m_pDataCursor->rowDeleted() ) |
| --nRecordCount; |
| |
| // there are no rows left and we have an insert row |
| if (!nRecordCount && GetEmptyRow().Is()) |
| { |
| Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY); |
| xUpdateCursor->moveToInsertRow(); |
| } |
| else if (nRecordCount) |
| // move to the first row |
| getDataSource()->first(); |
| } |
| } |
| // not all the rows where deleted, so move to the first row which remained in the resultset |
| else |
| { |
| for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++) |
| { |
| if (!pSuccess[i]) |
| { |
| getDataSource()->moveToBookmark(aBookmarks.getConstArray()[i]); |
| break; |
| } |
| } |
| } |
| } |
| catch(const Exception&) |
| { |
| try |
| { |
| // positioning went wrong so try to move to the first row |
| getDataSource()->first(); |
| } |
| catch(const Exception&) |
| { |
| } |
| } |
| |
| // An den DatenCursor anpassen |
| AdjustDataSource(sal_True); |
| |
| // es konnten nicht alle Zeilen geloescht werden |
| // da nie nicht geloeschten wieder selektieren |
| if (nDeletedRows < nSelectedRows) |
| { |
| // waren alle selektiert |
| if (bAllSelected) |
| { |
| SelectAll(); |
| if (IsInsertionRow(GetRowCount() - 1)) // einfuegeZeile nicht |
| SelectRow(GetRowCount() - 1, sal_False); |
| } |
| else |
| { |
| // select the remaining rows |
| for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++) |
| { |
| try |
| { |
| if (!pSuccess[i]) |
| { |
| m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark()); |
| SetSeekPos(m_pSeekCursor->getRow() - 1); |
| SelectRow(GetSeekPos()); |
| } |
| } |
| catch(const Exception&) |
| { |
| // keep the seekpos in all cases |
| SetSeekPos(m_pSeekCursor->getRow() - 1); |
| } |
| } |
| } |
| } |
| |
| EndCursorAction(); |
| SetUpdateMode(sal_True); |
| } |
| else // Zeile konnte nicht geloescht werden |
| { |
| EndCursorAction(); |
| try |
| { |
| // currentrow is the insert row? |
| if (!IsCurrentAppending()) |
| getDataSource()->refreshRow(); |
| } |
| catch(const Exception&) |
| { |
| } |
| } |
| } |
| |
| // if there is no selection anymore we can start editing |
| if (!GetSelectRowCount()) |
| ActivateCell(); |
| } |
| |
| |
| // XCurrentRecordListener |
| //------------------------------------------------------------------------------ |
| void FmGridControl::positioned(const ::com::sun::star::lang::EventObject& /*rEvent*/) |
| { |
| TRACE_RANGE("FmGridControl::positioned"); |
| // position on the data source (force it to be done in the main thread) |
| implAdjustInSolarThread(sal_False); |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Bool FmGridControl::commit() |
| { |
| // Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt |
| // wird |
| if (!IsUpdating()) |
| { |
| if (Controller().Is() && Controller()->IsModified()) |
| { |
| if (!SaveModified()) |
| return sal_False; |
| } |
| } |
| return sal_True; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::inserted(const ::com::sun::star::lang::EventObject& /*rEvent*/) |
| { |
| const DbGridRowRef& xRow = GetCurrentRow(); |
| if (!xRow.Is()) |
| return; |
| |
| // Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen |
| xRow->SetState(m_pDataCursor, sal_False); |
| xRow->SetNew(sal_False); |
| |
| } |
| |
| // XCancelUpdateRecordListener |
| //------------------------------------------------------------------------------ |
| void FmGridControl::restored(const ::com::sun::star::lang::EventObject& rEvent) |
| { |
| if (!GetCurrentRow().Is()) |
| return; |
| |
| sal_Bool bAppending = GetCurrentRow()->IsNew(); |
| sal_Bool bDirty = GetCurrentRow()->IsModified(); |
| if (bAppending && (EditBrowseBox::IsModified() || bDirty)) |
| { |
| if (Controller().Is()) |
| Controller()->ClearModified(); |
| |
| // jetzt die Zeile herausnehmen |
| RowRemoved(GetRowCount() - 1, 1, sal_True); |
| GetNavigationBar().InvalidateAll(); |
| } |
| |
| positioned(rEvent); |
| } |
| |
| //------------------------------------------------------------------------------ |
| BrowserHeader* FmGridControl::imp_CreateHeaderBar(BrowseBox* pParent) |
| { |
| DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" ); |
| return new FmGridHeader( pParent ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::markColumn(sal_uInt16 nId) |
| { |
| if (GetHeaderBar() && m_nMarkedColumnId != nId) |
| { |
| // deselektieren |
| if (m_nMarkedColumnId != BROWSER_INVALIDID) |
| { |
| HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HIB_FLAT; |
| GetHeaderBar()->SetItemBits(m_nMarkedColumnId, aBits); |
| } |
| |
| |
| if (nId != BROWSER_INVALIDID) |
| { |
| HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(nId) | HIB_FLAT; |
| GetHeaderBar()->SetItemBits(nId, aBits); |
| } |
| m_nMarkedColumnId = nId; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Bool FmGridControl::isColumnMarked(sal_uInt16 nId) const |
| { |
| return m_nMarkedColumnId == nId; |
| } |
| |
| //------------------------------------------------------------------------------ |
| long FmGridControl::QueryMinimumRowHeight() |
| { |
| long nMinimalLogicHeight = 20; // 0.2 cm |
| long nMinimalPixelHeight = LogicToPixel( Point( 0, nMinimalLogicHeight ), MAP_10TH_MM ).Y(); |
| return CalcZoom( nMinimalPixelHeight ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::RowHeightChanged() |
| { |
| DbGridControl::RowHeightChanged(); |
| |
| Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY ); |
| DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" ); |
| if ( xModel.is() ) |
| { |
| try |
| { |
| sal_Int32 nUnzoomedPixelHeight = CalcReverseZoom( GetDataRowHeight() ); |
| Any aProperty = makeAny( (sal_Int32)PixelToLogic( Point( 0, nUnzoomedPixelHeight ), MAP_10TH_MM ).Y() ); |
| xModel->setPropertyValue( FM_PROP_ROWHEIGHT, aProperty ); |
| } |
| catch( const Exception& ) |
| { |
| OSL_ENSURE( sal_False, "FmGridControl::RowHeightChanged: caught an exception!" ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::ColumnResized(sal_uInt16 nId) |
| { |
| DbGridControl::ColumnResized(nId); |
| |
| // Wert ans model uebergeben |
| DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId)); |
| Reference< ::com::sun::star::beans::XPropertySet > xColModel(pCol->getModel()); |
| if (xColModel.is()) |
| { |
| Any aWidth; |
| sal_Int32 nColumnWidth = GetColumnWidth(nId); |
| nColumnWidth = CalcReverseZoom(nColumnWidth); |
| // Umrechnen in 10THMM |
| aWidth <<= (sal_Int32)PixelToLogic(Point(nColumnWidth,0),MAP_10TH_MM).X(); |
| xColModel->setPropertyValue(FM_PROP_WIDTH, aWidth); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::CellModified() |
| { |
| DbGridControl::CellModified(); |
| GetPeer()->CellModified(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::BeginCursorAction() |
| { |
| DbGridControl::BeginCursorAction(); |
| m_pPeer->stopCursorListening(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::EndCursorAction() |
| { |
| m_pPeer->startCursorListening(); |
| DbGridControl::EndCursorAction(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::ColumnMoved(sal_uInt16 nId) |
| { |
| m_bInColumnMove = sal_True; |
| |
| DbGridControl::ColumnMoved(nId); |
| Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns()); |
| |
| if (xColumns.is()) |
| { |
| // suchen der Spalte und verschieben im Model |
| // ColumnPos holen |
| DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId)); |
| Reference< ::com::sun::star::beans::XPropertySet > xCol; |
| |
| // Einfuegen muß sich an den Column Positionen orientieren |
| sal_Int32 i; |
| Reference< XInterface > xCurrent; |
| for (i = 0; !xCol.is() && i < xColumns->getCount(); i++) |
| { |
| ::cppu::extractInterface(xCurrent, xColumns->getByIndex(i)); |
| if (xCurrent == pCol->getModel()) |
| { |
| xCol = pCol->getModel(); |
| break; |
| } |
| } |
| |
| DBG_ASSERT(i < xColumns->getCount(), "Falscher ::com::sun::star::sdbcx::Index"); |
| xColumns->removeByIndex(i); |
| Any aElement; |
| aElement <<= xCol; |
| xColumns->insertByIndex(GetModelColumnPos(nId), aElement); |
| pCol->setModel(xCol); |
| // if the column which is shown here is selected ... |
| if ( isColumnSelected(nId,pCol) ) |
| markColumn(nId); // ... -> mark it |
| } |
| |
| m_bInColumnMove = sal_False; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::InitColumnsByModels(const Reference< ::com::sun::star::container::XIndexContainer >& xColumns) |
| { |
| // Spalten wieder neu setzen |
| // wenn es nur eine HandleColumn gibt, dann nicht |
| if (GetModelColCount()) |
| { |
| RemoveColumns(); |
| InsertHandleColumn(); |
| } |
| |
| if (!xColumns.is()) |
| return; |
| |
| SetUpdateMode(sal_False); |
| |
| // Einfuegen mu� sich an den Column Positionen orientieren |
| sal_Int32 i; |
| String aName; |
| Any aWidth; |
| for (i = 0; i < xColumns->getCount(); ++i) |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xCol; |
| ::cppu::extractInterface(xCol, xColumns->getByIndex(i)); |
| |
| aName = ::comphelper::getString( xCol->getPropertyValue(FM_PROP_LABEL)).getStr(); |
| |
| aWidth = xCol->getPropertyValue(FM_PROP_WIDTH); |
| sal_Int32 nWidth = 0; |
| if (aWidth >>= nWidth) |
| nWidth = LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X(); |
| |
| AppendColumn(aName, (sal_uInt16)nWidth); |
| DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(i); |
| pCol->setModel(xCol); |
| } |
| |
| // und jetzt noch die hidden columns rausnehmen |
| // (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den |
| // IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_ |
| // einer versteckten braucht aber eine um eine erhoehte ID .... |
| Any aHidden; |
| for (i = 0; i < xColumns->getCount(); ++i) |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xCol; |
| ::cppu::extractInterface(xCol, xColumns->getByIndex(i)); |
| aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN); |
| if (::comphelper::getBOOL(aHidden)) |
| HideColumn(GetColumnIdFromModelPos((sal_uInt16)i)); |
| } |
| |
| SetUpdateMode(sal_True); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::InitColumnByField( |
| DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel, |
| const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex ) |
| { |
| DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" ); |
| |
| // lookup the column which belongs to the control source |
| ::rtl::OUString sFieldName; |
| _rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE ) >>= sFieldName; |
| Reference< XPropertySet > xField; |
| _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField; |
| |
| |
| if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length |
| _rxFieldsByNames->getByName( sFieldName ) >>= xField; |
| |
| // determine the position of this column |
| sal_Int32 nFieldPos = -1; |
| if ( xField.is() ) |
| { |
| Reference< XPropertySet > xCheck; |
| sal_Int32 nFieldCount = _rxFieldsByIndex->getCount(); |
| for ( sal_Int32 i = 0; i < nFieldCount; ++i) |
| { |
| _rxFieldsByIndex->getByIndex( i ) >>= xCheck; |
| if ( xField.get() == xCheck.get() ) |
| { |
| nFieldPos = i; |
| break; |
| } |
| } |
| } |
| |
| if ( xField.is() && ( nFieldPos >= 0 ) ) |
| { |
| // some data types are not allowed |
| sal_Int32 nDataType = DataType::OTHER; |
| xField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType; |
| |
| sal_Bool bIllegalType = sal_False; |
| switch ( nDataType ) |
| { |
| case DataType::BLOB: |
| case DataType::LONGVARBINARY: |
| case DataType::BINARY: |
| case DataType::VARBINARY: |
| case DataType::OTHER: |
| bIllegalType = sal_True; |
| break; |
| } |
| |
| if ( bIllegalType ) |
| { |
| _pColumn->SetObject( (sal_Int16)nFieldPos ); |
| return; |
| } |
| /* |
| // handle readonly columns |
| sal_Bool bReadOnly = sal_True; |
| xField->getPropertyValue( FM_PROP_ISREADONLY ) >>= bReadOnly; |
| _pColumn->SetReadOnly( bReadOnly ); |
| */ |
| } |
| |
| // the control type is determined by the ColumnServiceName |
| static ::rtl::OUString s_sPropColumnServiceName( RTL_CONSTASCII_USTRINGPARAM( "ColumnServiceName" ) ); |
| if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) ) |
| return; |
| |
| _pColumn->setModel( _rxColumnModel ); |
| |
| ::rtl::OUString sColumnServiceName; |
| _rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName; |
| |
| sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName ); |
| _pColumn->CreateControl( nFieldPos, xField, nTypeId ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::InitColumnsByFields(const Reference< ::com::sun::star::container::XIndexAccess >& _rxFields) |
| { |
| if ( !_rxFields.is() ) |
| return; |
| |
| // Spalten initialisieren |
| Reference< XIndexContainer > xColumns( GetPeer()->getColumns() ); |
| Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY ); |
| |
| // Einfuegen muss sich an den Column Positionen orientieren |
| for (sal_Int32 i = 0; i < xColumns->getCount(); i++) |
| { |
| DbGridColumn* pCol = GetColumns().GetObject(i); |
| OSL_ENSURE(pCol,"No grid column!"); |
| if ( pCol ) |
| { |
| Reference< XPropertySet > xColumnModel; |
| ::cppu::extractInterface( xColumnModel, xColumns->getByIndex( i ) ); |
| |
| InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::HideColumn(sal_uInt16 nId) |
| { |
| DbGridControl::HideColumn(nId); |
| |
| sal_uInt16 nPos = GetModelColumnPos(nId); |
| if (nPos == (sal_uInt16)-1) |
| return; |
| |
| DbGridColumn* pColumn = GetColumns().GetObject(nPos); |
| if (pColumn->IsHidden()) |
| GetPeer()->columnHidden(pColumn); |
| |
| if (nId == m_nMarkedColumnId) |
| m_nMarkedColumnId = (sal_uInt16)-1; |
| } |
| // ----------------------------------------------------------------------------- |
| sal_Bool FmGridControl::isColumnSelected(sal_uInt16 /*nId*/,DbGridColumn* _pColumn) |
| { |
| OSL_ENSURE(_pColumn,"Column can not be null!"); |
| sal_Bool bSelected = sal_False; |
| // if the column which is shown here is selected ... |
| Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(GetPeer()->getColumns(), UNO_QUERY); |
| if ( xSelSupplier.is() ) |
| { |
| Reference< ::com::sun::star::beans::XPropertySet > xColumn; |
| xSelSupplier->getSelection() >>= xColumn; |
| bSelected = (xColumn.get() == _pColumn->getModel().get()); |
| } |
| return bSelected; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void FmGridControl::ShowColumn(sal_uInt16 nId) |
| { |
| DbGridControl::ShowColumn(nId); |
| |
| sal_uInt16 nPos = GetModelColumnPos(nId); |
| if (nPos == (sal_uInt16)-1) |
| return; |
| |
| DbGridColumn* pColumn = GetColumns().GetObject(nPos); |
| if (!pColumn->IsHidden()) |
| GetPeer()->columnVisible(pColumn); |
| |
| // if the column which is shown here is selected ... |
| if ( isColumnSelected(nId,pColumn) ) |
| markColumn(nId); // ... -> mark it |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks) |
| { |
| vos::OGuard aGuard( Application::GetSolarMutex() ); |
| // need to lock the SolarMutex so that no paint call disturbs us ... |
| |
| if ( !m_pSeekCursor ) |
| { |
| DBG_ERROR( "FmGridControl::selectBookmarks: no seek cursor!" ); |
| return sal_False; |
| } |
| |
| const Any* pBookmark = _rBookmarks.getConstArray(); |
| const Any* pBookmarkEnd = pBookmark + _rBookmarks.getLength(); |
| |
| SetNoSelection(); |
| |
| sal_Bool bAllSuccessfull = sal_True; |
| try |
| { |
| for (; pBookmark != pBookmarkEnd; ++pBookmark) |
| { |
| // move the seek cursor to the row given |
| if (m_pSeekCursor->moveToBookmark(*pBookmark)) |
| SelectRow( m_pSeekCursor->getRow() - 1); |
| else |
| bAllSuccessfull = sal_False; |
| } |
| } |
| catch(Exception&) |
| { |
| DBG_ERROR("FmGridControl::selectBookmarks: could not move to one of the bookmarks!"); |
| return sal_False; |
| } |
| |
| return bAllSuccessfull; |
| } |
| |
| //------------------------------------------------------------------------------ |
| Sequence< Any> FmGridControl::getSelectionBookmarks() |
| { |
| // lock our update so no paint-triggered seeks interfere ... |
| SetUpdateMode(sal_False); |
| |
| sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0; |
| Sequence< Any> aBookmarks(nSelectedRows); |
| if ( nSelectedRows ) |
| { |
| Any* pBookmarks = (Any*)aBookmarks.getArray(); |
| |
| // (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a |
| // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress |
| // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a |
| // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition. |
| // Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the |
| // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning |
| // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails. |
| // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on |
| // the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these |
| // code parts is executed, no other should be accessible. But this sounds very difficult to achieve .... |
| // ) |
| |
| // The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly |
| // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results. |
| // That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks. |
| long nIdx = FirstSelectedRow(); |
| while (nIdx >= 0) |
| { |
| // (we misuse the bookmarks array for this ...) |
| pBookmarks[i++] <<= (sal_Int32)nIdx; |
| nIdx = NextSelectedRow(); |
| } |
| DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !"); |
| |
| for (i=0; i<nSelectedRows; ++i) |
| { |
| nIdx = ::comphelper::getINT32(pBookmarks[i]); |
| if (IsInsertionRow(nIdx)) |
| { |
| // leerzeile nicht loeschen |
| aBookmarks.realloc(--nSelectedRows); |
| SelectRow(nIdx,sal_False); // selection aufheben fuer leerzeile |
| break; |
| } |
| |
| // Zunaechst den DatenCursor auf den selektierten Satz pos. |
| if (SeekCursor(nIdx)) |
| { |
| GetSeekRow()->SetState(m_pSeekCursor, sal_True); |
| |
| pBookmarks[i] = m_pSeekCursor->getBookmark(); |
| } |
| #ifdef DBG_UTIL |
| else |
| DBG_ERROR("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !"); |
| #endif |
| } |
| } |
| SetUpdateMode(sal_True); |
| |
| // if one of the SeekCursor-calls failed .... |
| aBookmarks.realloc(i); |
| |
| // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems. |
| // but this would be incompatible as we need a locking flag, then ...) |
| |
| return aBookmarks; |
| } |
| // ----------------------------------------------------------------------------- |
| namespace |
| { |
| ::rtl::OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const ::rtl::OUString& _sPropName) |
| { |
| ::rtl::OUString sRetText; |
| if ( _pPeer && _nPosition != -1) |
| { |
| Reference<XIndexContainer> xIndex = _pPeer->getColumns(); |
| if ( xIndex.is() && xIndex->getCount() > _nPosition ) |
| { |
| Reference<XPropertySet> xProp; |
| xIndex->getByIndex( _nPosition ) >>= xProp; |
| if ( xProp.is() ) |
| xProp->getPropertyValue( _sPropName ) >>= sRetText; |
| } |
| } |
| return sRetText; |
| } |
| } |
| // Object data and state ------------------------------------------------------ |
| ::rtl::OUString FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const |
| { |
| ::rtl::OUString sRetText; |
| switch( _eObjType ) |
| { |
| case ::svt::BBTYPE_BROWSEBOX: |
| if ( GetPeer() ) |
| { |
| Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY); |
| if ( xProp.is() ) |
| xProp->getPropertyValue(FM_PROP_NAME) >>= sRetText; |
| } |
| break; |
| case ::svt::BBTYPE_COLUMNHEADERCELL: |
| sRetText = getColumnPropertyFromPeer( |
| GetPeer(), |
| GetModelColumnPos( |
| sal::static_int_cast< sal_uInt16 >(_nPosition)), |
| FM_PROP_LABEL); |
| break; |
| default: |
| sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition); |
| } |
| return sRetText; |
| } |
| // ----------------------------------------------------------------------------- |
| |
| ::rtl::OUString FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const |
| { |
| ::rtl::OUString sRetText; |
| switch( _eObjType ) |
| { |
| case ::svt::BBTYPE_BROWSEBOX: |
| if ( GetPeer() ) |
| { |
| Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY); |
| if ( xProp.is() ) |
| { |
| xProp->getPropertyValue(FM_PROP_HELPTEXT) >>= sRetText; |
| if ( !sRetText.getLength() ) |
| xProp->getPropertyValue(FM_PROP_DESCRIPTION) >>= sRetText; |
| } |
| } |
| break; |
| case ::svt::BBTYPE_COLUMNHEADERCELL: |
| sRetText = getColumnPropertyFromPeer( |
| GetPeer(), |
| GetModelColumnPos( |
| sal::static_int_cast< sal_uInt16 >(_nPosition)), |
| FM_PROP_HELPTEXT); |
| if ( !sRetText.getLength() ) |
| sRetText = getColumnPropertyFromPeer( |
| GetPeer(), |
| GetModelColumnPos( |
| sal::static_int_cast< sal_uInt16 >(_nPosition)), |
| FM_PROP_DESCRIPTION); |
| |
| break; |
| default: |
| sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition); |
| } |
| return sRetText; |
| } |
| // ----------------------------------------------------------------------------- |
| void FmGridControl::Select() |
| { |
| DbGridControl::Select(); |
| // ... betrifft das unsere Spalten ? |
| const MultiSelection* pColumnSelection = GetColumnSelection(); |
| |
| sal_uInt16 nSelectedColumn = |
| pColumnSelection && pColumnSelection->GetSelectCount() |
| ? sal::static_int_cast< sal_uInt16 >( |
| ((MultiSelection*)pColumnSelection)->FirstSelected()) |
| : SAL_MAX_UINT16; |
| // die HandleColumn wird nicht selektiert |
| switch (nSelectedColumn) |
| { |
| case SAL_MAX_UINT16: break; // no selection |
| case 0 : nSelectedColumn = SAL_MAX_UINT16; break; |
| // handle col can't be seledted |
| default : |
| // get the model col pos instead of the view col pos |
| nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1)); |
| break; |
| } |
| |
| if (nSelectedColumn != m_nCurrentSelectedColumn) |
| { |
| // VOR dem Aufruf des select am SelectionSupplier ! |
| m_nCurrentSelectedColumn = nSelectedColumn; |
| |
| if (!m_bSelecting) |
| { |
| m_bSelecting = sal_True; |
| |
| try |
| { |
| Reference< XIndexAccess > xColumns(GetPeer()->getColumns(), UNO_QUERY); |
| Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); |
| if (xSelSupplier.is()) |
| { |
| if (nSelectedColumn != SAL_MAX_UINT16) |
| { |
| Reference< XPropertySet > xColumn; |
| ::cppu::extractInterface(xColumn,xColumns->getByIndex(nSelectedColumn)); |
| xSelSupplier->select(makeAny(xColumn)); |
| } |
| else |
| { |
| xSelSupplier->select(Any()); |
| } |
| } |
| } |
| catch(Exception&) |
| { |
| } |
| |
| |
| m_bSelecting = sal_False; |
| } |
| } |
| } |
| // ----------------------------------------------------------------------------- |
| sal_Int32 FmGridControl::GetSelectedColumn() const |
| { |
| return m_nCurrentSelectedColumn; |
| } |
| // ----------------------------------------------------------------------------- |
| void FmGridControl::KeyInput( const KeyEvent& rKEvt ) |
| { |
| sal_Bool bDone = sal_False; |
| const KeyCode& rKeyCode = rKEvt.GetKeyCode(); |
| if ( IsDesignMode() |
| && !rKeyCode.IsShift() |
| && !rKeyCode.IsMod1() |
| && !rKeyCode.IsMod2() |
| && GetParent() ) |
| { |
| switch ( rKeyCode.GetCode() ) |
| { |
| case KEY_ESCAPE: |
| GetParent()->GrabFocus(); |
| bDone = sal_True; |
| break; |
| case KEY_DELETE: |
| if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn >= 0 ) |
| { |
| Reference< ::com::sun::star::container::XIndexContainer > xCols(GetPeer()->getColumns()); |
| if ( xCols.is() ) |
| { |
| try |
| { |
| if ( m_nCurrentSelectedColumn < xCols->getCount() ) |
| { |
| Reference< XInterface > xCol; |
| xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol; |
| xCols->removeByIndex(m_nCurrentSelectedColumn); |
| ::comphelper::disposeComponent(xCol); |
| } |
| } |
| catch(const Exception&) |
| { |
| OSL_ENSURE(0,"exception occured while deleting a column"); |
| } |
| } |
| } |
| bDone = sal_True; |
| break; |
| } |
| } |
| if ( !bDone ) |
| DbGridControl::KeyInput( rKEvt ); |
| } |
| // ----------------------------------------------------------------------------- |
| |
| |
| |