1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svx.hxx" 26 27 #include "svx/dbexch.hrc" 28 #include "svx/fmgridif.hxx" 29 #include "fmitems.hxx" 30 #include "fmprop.hrc" 31 #include "svx/fmtools.hxx" 32 #include "svx/fmresids.hrc" 33 #include "fmservs.hxx" 34 #include "fmurl.hxx" 35 #include "formcontrolfactory.hxx" 36 #include "gridcell.hxx" 37 #include "gridcols.hxx" 38 #include "svx/dbaexchange.hxx" 39 #include "svx/dialmgr.hxx" 40 #include "svx/dialogs.hrc" 41 #include "svx/fmgridcl.hxx" 42 #include "svx/svxdlg.hxx" 43 #include "svx/svxids.hrc" 44 #include "trace.hxx" 45 46 #include <com/sun/star/form/XConfirmDeleteListener.hpp> 47 #include <com/sun/star/form/XFormComponent.hpp> 48 #include <com/sun/star/form/XGridColumnFactory.hpp> 49 #include <com/sun/star/io/XPersistObject.hpp> 50 #include <com/sun/star/sdb/CommandType.hpp> 51 #include <com/sun/star/sdb/RowChangeAction.hpp> 52 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 53 #include <com/sun/star/sdbc/DataType.hpp> 54 #include <com/sun/star/sdbc/XPreparedStatement.hpp> 55 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 56 #include <com/sun/star/sdbcx/XDeleteRows.hpp> 57 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 58 #include <com/sun/star/uno/XNamingService.hpp> 59 #include <com/sun/star/util/XNumberFormats.hpp> 60 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 61 #include <com/sun/star/util/XURLTransformer.hpp> 62 #include <com/sun/star/view/XSelectionSupplier.hpp> 63 64 #ifndef _SVSTDARR_STRINGSDTOR 65 #define _SVSTDARR_STRINGSDTOR 66 #define _SVSTDARR_ULONGS 67 #include <svl/svstdarr.hxx> 68 #endif 69 70 #include <comphelper/extract.hxx> 71 #include <comphelper/numbers.hxx> 72 #include <comphelper/processfactory.hxx> 73 #include <comphelper/property.hxx> 74 #include <connectivity/dbtools.hxx> 75 #include <sfx2/dispatch.hxx> 76 #include <sfx2/viewfrm.hxx> 77 #include <svl/eitem.hxx> 78 #include <svtools/fmtfield.hxx> 79 #include <svl/numuno.hxx> 80 #include <tools/multisel.hxx> 81 #include <tools/shl.hxx> 82 #include <tools/diagnose_ex.h> 83 #include <vcl/help.hxx> 84 #include <vcl/image.hxx> 85 #include <vcl/longcurr.hxx> 86 #include <vcl/menu.hxx> 87 88 #include <math.h> 89 90 using namespace ::com::sun::star::uno; 91 using namespace ::com::sun::star::view; 92 using namespace ::com::sun::star::beans; 93 using namespace ::com::sun::star::lang; 94 using namespace ::com::sun::star::sdbcx; 95 using namespace ::com::sun::star::sdbc; 96 using namespace ::com::sun::star::sdb; 97 using namespace ::com::sun::star::form; 98 using namespace ::com::sun::star::util; 99 using namespace ::com::sun::star::container; 100 using namespace ::cppu; 101 using namespace ::svxform; 102 using namespace ::svx; 103 104 //============================================================================== 105 //------------------------------------------------------------------------------ 106 ::rtl::OUString FieldServiceFromId(sal_Int32 nID) 107 { 108 switch (nID) 109 { 110 case SID_FM_EDIT : return FM_COL_TEXTFIELD; 111 case SID_FM_COMBOBOX : return FM_COL_COMBOBOX; 112 case SID_FM_LISTBOX : return FM_COL_LISTBOX; 113 case SID_FM_CHECKBOX : return FM_COL_CHECKBOX; 114 case SID_FM_DATEFIELD : return FM_COL_DATEFIELD; 115 case SID_FM_TIMEFIELD : return FM_COL_TIMEFIELD; 116 case SID_FM_NUMERICFIELD : return FM_COL_NUMERICFIELD; 117 case SID_FM_CURRENCYFIELD : return FM_COL_CURRENCYFIELD; 118 case SID_FM_PATTERNFIELD : return FM_COL_PATTERNFIELD; 119 case SID_FM_FORMATTEDFIELD : return FM_COL_FORMATTEDFIELD; 120 } 121 return ::rtl::OUString(); 122 } 123 124 //============================================================================== 125 struct FmGridHeaderData 126 { 127 ODataAccessDescriptor aDropData; 128 Point aDropPosPixel; 129 sal_Int8 nDropAction; 130 Reference< XInterface > xDroppedStatement; 131 Reference< XInterface > xDroppedResultSet; 132 }; 133 134 //============================================================================== 135 //------------------------------------------------------------------------------ 136 const sal_Int16 nChangeTypeOffset = 1000; 137 void SetMenuItem(const ImageList& rList, sal_uInt16 nID, Menu* pMenu, Menu& rNewMenu, sal_Bool bDesignMode = sal_True, sal_Int16 nOffset = nChangeTypeOffset) 138 { 139 pMenu->SetItemImage(nID, rList.GetImage(nID)); 140 pMenu->EnableItem(nID, bDesignMode); 141 rNewMenu.InsertItem(nID + nOffset, pMenu->GetItemText(nID)); 142 rNewMenu.SetItemImage(nID + nOffset, rList.GetImage(nID)); 143 rNewMenu.SetHelpId(nID + nOffset, pMenu->GetHelpId(nID)); 144 rNewMenu.EnableItem(nID + nOffset, bDesignMode); 145 } 146 147 //------------------------------------------------------------------------------ 148 FmGridHeader::FmGridHeader( BrowseBox* pParent, WinBits nWinBits) 149 :EditBrowserHeader(pParent, nWinBits) 150 ,DropTargetHelper(this) 151 ,m_pImpl(new FmGridHeaderData) 152 { 153 } 154 155 //------------------------------------------------------------------------------ 156 FmGridHeader::~FmGridHeader() 157 { 158 delete m_pImpl; 159 } 160 161 //------------------------------------------------------------------------------ 162 sal_uInt16 FmGridHeader::GetModelColumnPos(sal_uInt16 nId) const 163 { 164 return static_cast<FmGridControl*>(GetParent())->GetModelColumnPos(nId); 165 } 166 //--------------------------------------------------------------------------------------- 167 void FmGridHeader::notifyColumnSelect(sal_uInt16 nColumnId) 168 { 169 sal_uInt16 nPos = GetModelColumnPos(nColumnId); 170 Reference< XIndexAccess > xColumns(((FmGridControl*)GetParent())->GetPeer()->getColumns(), UNO_QUERY); 171 if ( nPos < xColumns->getCount() ) 172 { 173 Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); 174 if ( xSelSupplier.is() ) 175 { 176 Reference< XPropertySet > xColumn; 177 xColumns->getByIndex(nPos) >>= xColumn; 178 xSelSupplier->select(makeAny(xColumn)); 179 } 180 } 181 } 182 //------------------------------------------------------------------------------ 183 void FmGridHeader::Select() 184 { 185 EditBrowserHeader::Select(); 186 notifyColumnSelect(GetCurItemId()); 187 } 188 189 //------------------------------------------------------------------------------ 190 void FmGridHeader::RequestHelp( const HelpEvent& rHEvt ) 191 { 192 sal_uInt16 nItemId = GetItemId( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) ); 193 if ( nItemId ) 194 { 195 if ( rHEvt.GetMode() & (HELPMODE_QUICK | HELPMODE_BALLOON) ) 196 { 197 Rectangle aItemRect = GetItemRect( nItemId ); 198 Point aPt = OutputToScreenPixel( aItemRect.TopLeft() ); 199 aItemRect.Left() = aPt.X(); 200 aItemRect.Top() = aPt.Y(); 201 aPt = OutputToScreenPixel( aItemRect.BottomRight() ); 202 aItemRect.Right() = aPt.X(); 203 aItemRect.Bottom() = aPt.Y(); 204 205 sal_uInt16 nPos = GetModelColumnPos(nItemId); 206 Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); 207 try 208 { 209 Reference< ::com::sun::star::beans::XPropertySet > xColumn(xColumns->getByIndex(nPos),UNO_QUERY); 210 ::rtl::OUString aHelpText; 211 xColumn->getPropertyValue(FM_PROP_HELPTEXT) >>= aHelpText; 212 if ( !aHelpText.getLength() ) 213 xColumn->getPropertyValue(FM_PROP_DESCRIPTION) >>= aHelpText; 214 if ( aHelpText.getLength() ) 215 { 216 if ( rHEvt.GetMode() & HELPMODE_BALLOON ) 217 Help::ShowBalloon( this, aItemRect.Center(), aItemRect, aHelpText ); 218 else 219 Help::ShowQuickHelp( this, aItemRect, aHelpText ); 220 return; 221 } 222 } 223 catch(Exception&) 224 { 225 return; 226 } 227 } 228 } 229 EditBrowserHeader::RequestHelp( rHEvt ); 230 } 231 232 //------------------------------------------------------------------------------ 233 sal_Int8 FmGridHeader::AcceptDrop( const AcceptDropEvent& rEvt ) 234 { 235 // drop allowed in design mode only 236 if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode()) 237 return DND_ACTION_NONE; 238 239 // search for recognized formats 240 const DataFlavorExVector& rFlavors = GetDataFlavorExVector(); 241 if (OColumnTransferable::canExtractColumnDescriptor(rFlavors, CTF_COLUMN_DESCRIPTOR | CTF_FIELD_DESCRIPTOR)) 242 return rEvt.mnAction; 243 244 return DND_ACTION_NONE; 245 } 246 247 //------------------------------------------------------------------------------ 248 sal_Int8 FmGridHeader::ExecuteDrop( const ExecuteDropEvent& _rEvt ) 249 { 250 if (!static_cast<FmGridControl*>(GetParent())->IsDesignMode()) 251 return DND_ACTION_NONE; 252 253 TransferableDataHelper aDroppedData(_rEvt.maDropEvent.Transferable); 254 255 // check the formats 256 sal_Bool bColumnDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_COLUMN_DESCRIPTOR); 257 sal_Bool bFieldDescriptor = OColumnTransferable::canExtractColumnDescriptor(aDroppedData.GetDataFlavorExVector(), CTF_FIELD_DESCRIPTOR); 258 if (!bColumnDescriptor && !bFieldDescriptor) 259 { 260 DBG_ERROR("FmGridHeader::ExecuteDrop: should never have reached this (no extractable format)!"); 261 return DND_ACTION_NONE; 262 } 263 264 // extract the descriptor 265 ::rtl::OUString sDatasouce, sCommand, sFieldName,sDatabaseLocation,sConnnectionResource; 266 sal_Int32 nCommandType = CommandType::COMMAND; 267 Reference< XPreparedStatement > xStatement; 268 Reference< XResultSet > xResultSet; 269 Reference< XPropertySet > xField; 270 Reference< XConnection > xConnection; 271 272 ODataAccessDescriptor aColumn = OColumnTransferable::extractColumnDescriptor(aDroppedData); 273 if (aColumn.has(daDataSource)) aColumn[daDataSource] >>= sDatasouce; 274 if (aColumn.has(daDatabaseLocation)) aColumn[daDatabaseLocation] >>= sDatabaseLocation; 275 if (aColumn.has(daConnectionResource)) aColumn[daConnectionResource] >>= sConnnectionResource; 276 if (aColumn.has(daCommand)) aColumn[daCommand] >>= sCommand; 277 if (aColumn.has(daCommandType)) aColumn[daCommandType] >>= nCommandType; 278 if (aColumn.has(daColumnName)) aColumn[daColumnName] >>= sFieldName; 279 if (aColumn.has(daColumnObject))aColumn[daColumnObject] >>= xField; 280 if (aColumn.has(daConnection)) aColumn[daConnection] >>= xConnection; 281 282 if ( !sFieldName.getLength() 283 || !sCommand.getLength() 284 || ( !sDatasouce.getLength() 285 && !sDatabaseLocation.getLength() 286 && !xConnection.is() 287 ) 288 ) 289 { 290 DBG_ERROR( "FmGridHeader::ExecuteDrop: somebody started a nonsense drag operation!!" ); 291 return DND_ACTION_NONE; 292 } 293 294 try 295 { 296 // need a connection 297 if (!xConnection.is()) 298 { // the transferable did not contain the connection -> build an own one 299 try 300 { 301 ::rtl::OUString sSignificantSource( sDatasouce.getLength() ? sDatasouce : sDatabaseLocation ); 302 xConnection = OStaticDataAccessTools().getConnection_withFeedback(sSignificantSource, ::rtl::OUString(),::rtl::OUString(),static_cast<FmGridControl*>(GetParent())->getServiceManager()); 303 } 304 catch(NoSuchElementException&) 305 { // allowed, means sDatasouce isn't a valid data source name .... 306 } 307 catch(Exception&) 308 { 309 DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !"); 310 } 311 312 if (!xConnection.is()) 313 { 314 DBG_ERROR("FmGridHeader::ExecuteDrop: could not retrieve the database access object !"); 315 return DND_ACTION_NONE; 316 } 317 } 318 319 // try to obtain the column object 320 if (!xField.is()) 321 { 322 #ifdef DBG_UTIL 323 Reference< XServiceInfo > xServiceInfo(xConnection, UNO_QUERY); 324 DBG_ASSERT(xServiceInfo.is() && xServiceInfo->supportsService(SRV_SDB_CONNECTION), "FmGridHeader::ExecuteDrop: invalid connection (no database access connection !)"); 325 #endif 326 327 Reference< XNameAccess > xFields; 328 switch (nCommandType) 329 { 330 case CommandType::TABLE: 331 { 332 Reference< XTablesSupplier > xSupplyTables(xConnection, UNO_QUERY); 333 Reference< XColumnsSupplier > xSupplyColumns; 334 xSupplyTables->getTables()->getByName(sCommand) >>= xSupplyColumns; 335 xFields = xSupplyColumns->getColumns(); 336 } 337 break; 338 case CommandType::QUERY: 339 { 340 Reference< XQueriesSupplier > xSupplyQueries(xConnection, UNO_QUERY); 341 Reference< XColumnsSupplier > xSupplyColumns; 342 xSupplyQueries->getQueries()->getByName(sCommand) >>= xSupplyColumns; 343 xFields = xSupplyColumns->getColumns(); 344 } 345 break; 346 default: 347 { 348 xStatement = xConnection->prepareStatement(sCommand); 349 // not interested in any results 350 351 Reference< XPropertySet > xStatProps(xStatement,UNO_QUERY); 352 xStatProps->setPropertyValue(rtl::OUString::createFromAscii("MaxRows"), makeAny(sal_Int32(0))); 353 354 xResultSet = xStatement->executeQuery(); 355 Reference< XColumnsSupplier > xSupplyCols(xResultSet, UNO_QUERY); 356 if (xSupplyCols.is()) 357 xFields = xSupplyCols->getColumns(); 358 } 359 } 360 361 if (xFields.is() && xFields->hasByName(sFieldName)) 362 xFields->getByName(sFieldName) >>= xField; 363 364 if (!xField.is()) 365 { 366 ::comphelper::disposeComponent(xStatement); 367 return DND_ACTION_NONE; 368 } 369 } 370 371 // do the drop asynchronously 372 // (85957 - UI actions within the drop are not allowed, but we want to open a popup menu) 373 m_pImpl->aDropData = aColumn; 374 m_pImpl->aDropData[daConnection] <<= xConnection; 375 m_pImpl->aDropData[daColumnObject] <<= xField; 376 377 m_pImpl->nDropAction = _rEvt.mnAction; 378 m_pImpl->aDropPosPixel = _rEvt.maPosPixel; 379 m_pImpl->xDroppedStatement = xStatement; 380 m_pImpl->xDroppedResultSet = xResultSet; 381 382 PostUserEvent(LINK(this, FmGridHeader, OnAsyncExecuteDrop)); 383 } 384 catch (Exception&) 385 { 386 DBG_ERROR("FmGridHeader::ExecuteDrop: caught an exception while creatin' the column !"); 387 ::comphelper::disposeComponent(xStatement); 388 return sal_False; 389 } 390 391 return DND_ACTION_LINK; 392 } 393 394 //------------------------------------------------------------------------------ 395 IMPL_LINK( FmGridHeader, OnAsyncExecuteDrop, void*, /*NOTINTERESTEDIN*/ ) 396 { 397 ::rtl::OUString sCommand, sFieldName,sURL; 398 sal_Int32 nCommandType = CommandType::COMMAND; 399 Reference< XPropertySet > xField; 400 Reference< XConnection > xConnection; 401 402 ::rtl::OUString sDatasouce = m_pImpl->aDropData.getDataSource(); 403 if ( !sDatasouce.getLength() && m_pImpl->aDropData.has(daConnectionResource) ) 404 m_pImpl->aDropData[daConnectionResource] >>= sURL; 405 m_pImpl->aDropData[daCommand] >>= sCommand; 406 m_pImpl->aDropData[daCommandType] >>= nCommandType; 407 m_pImpl->aDropData[daColumnName] >>= sFieldName; 408 m_pImpl->aDropData[daConnection] >>= xConnection; 409 m_pImpl->aDropData[daColumnObject] >>= xField; 410 411 try 412 { 413 // need number formats 414 Reference< XNumberFormatsSupplier > xSupplier = OStaticDataAccessTools().getNumberFormats(xConnection, sal_True); 415 Reference< XNumberFormats > xNumberFormats; 416 if (xSupplier.is()) 417 xNumberFormats = xSupplier->getNumberFormats(); 418 if (!xNumberFormats.is()) 419 { 420 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); 421 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); 422 return 0L; 423 } 424 425 // Vom Feld werden nun zwei Informationen benoetigt: 426 // a.) Name des Feldes fuer Label und ControlSource 427 // b.) FormatKey, um festzustellen, welches Feld erzeugt werden soll 428 sal_Int32 nDataType = 0; 429 xField->getPropertyValue(FM_PROP_FIELDTYPE) >>= nDataType; 430 // diese Datentypen koennen im Gridcontrol nicht verarbeitet werden 431 switch (nDataType) 432 { 433 case DataType::BLOB: 434 case DataType::LONGVARBINARY: 435 case DataType::BINARY: 436 case DataType::VARBINARY: 437 case DataType::OTHER: 438 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); 439 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); 440 return 0L; 441 } 442 443 // Erstellen der Column 444 Reference< XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); 445 Reference< XGridColumnFactory > xFactory(xCols, UNO_QUERY); 446 447 Point aPos = OutputToScreenPixel(m_pImpl->aDropPosPixel); 448 sal_uInt16 nColId = GetItemId(m_pImpl->aDropPosPixel); 449 // EinfuegePosition, immer vor der aktuellen Spalte 450 sal_uInt16 nPos = GetModelColumnPos(nColId); 451 Reference< XPropertySet > xCol, xSecondCol; 452 453 // erzeugen der Column in abhaengigkeit vom type, default textfeld 454 SvULongs aPossibleTypes; 455 switch (nDataType) 456 { 457 case DataType::BIT: 458 case DataType::BOOLEAN: 459 aPossibleTypes.Insert(SID_FM_CHECKBOX, aPossibleTypes.Count()); 460 break; 461 case DataType::TINYINT: 462 case DataType::SMALLINT: 463 case DataType::INTEGER: 464 aPossibleTypes.Insert(SID_FM_NUMERICFIELD, aPossibleTypes.Count()); 465 aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); 466 break; 467 case DataType::REAL: 468 case DataType::DOUBLE: 469 case DataType::NUMERIC: 470 case DataType::DECIMAL: 471 aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); 472 aPossibleTypes.Insert(SID_FM_NUMERICFIELD, aPossibleTypes.Count()); 473 break; 474 case DataType::TIMESTAMP: 475 aPossibleTypes.Insert(SID_FM_TWOFIELDS_DATE_N_TIME, aPossibleTypes.Count()); 476 aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count()); 477 aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count()); 478 aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); 479 break; 480 case DataType::DATE: 481 aPossibleTypes.Insert(SID_FM_DATEFIELD, aPossibleTypes.Count()); 482 aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); 483 break; 484 case DataType::TIME: 485 aPossibleTypes.Insert(SID_FM_TIMEFIELD, aPossibleTypes.Count()); 486 aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); 487 break; 488 case DataType::CHAR: 489 case DataType::VARCHAR: 490 case DataType::LONGVARCHAR: 491 default: 492 aPossibleTypes.Insert(SID_FM_EDIT, aPossibleTypes.Count()); 493 aPossibleTypes.Insert(SID_FM_FORMATTEDFIELD, aPossibleTypes.Count()); 494 break; 495 } 496 // if it's a currency field, a a "currency field" option 497 try 498 { 499 if ( ::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField) 500 && ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY))) 501 aPossibleTypes.Insert(SID_FM_CURRENCYFIELD, 0); 502 } 503 catch(Exception&) 504 { 505 DBG_ERROR("FmGridHeader::ExecuteDrop: Exception occured!"); 506 } 507 508 sal_Int32 nPreferedType = -1; 509 sal_Bool bDateNTimeCol = sal_False; 510 if (aPossibleTypes.Count() != 0) 511 { 512 nPreferedType = aPossibleTypes[0]; 513 if ((m_pImpl->nDropAction == DND_ACTION_LINK) && (aPossibleTypes.Count() > 1)) 514 { 515 ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) ); 516 517 PopupMenu aInsertMenu(SVX_RES(RID_SVXMNU_COLS)); 518 PopupMenu aTypeMenu; 519 PopupMenu* pMenu = aInsertMenu.GetPopupMenu(SID_FM_INSERTCOL); 520 for (sal_uInt32 i=0; i<aPossibleTypes.Count(); ++i) 521 SetMenuItem(aImageList, sal_uInt16(aPossibleTypes[(sal_uInt16)i]), pMenu, aTypeMenu, sal_True, 0); 522 nPreferedType = aTypeMenu.Execute(this, m_pImpl->aDropPosPixel); 523 } 524 525 bDateNTimeCol = nPreferedType == SID_FM_TWOFIELDS_DATE_N_TIME; 526 sal_uInt16 nColCount = bDateNTimeCol ? 2 : 1; 527 ::rtl::OUString sFieldService; 528 while (nColCount--) 529 { 530 if (bDateNTimeCol) 531 nPreferedType = nColCount ? SID_FM_DATEFIELD : SID_FM_TIMEFIELD; 532 533 sFieldService = FieldServiceFromId(nPreferedType); 534 Reference< XPropertySet > xThisRoundCol; 535 if ( sFieldService.getLength() ) 536 xThisRoundCol = xFactory->createColumn(sFieldService); 537 if (nColCount) 538 xSecondCol = xThisRoundCol; 539 else 540 xCol = xThisRoundCol; 541 } 542 } 543 544 if (!xCol.is() || (bDateNTimeCol && !xSecondCol.is())) 545 { 546 ::comphelper::disposeComponent(xCol); // in case only the creation of the second column failed 547 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); 548 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); 549 return 0L; 550 } 551 552 if (bDateNTimeCol) 553 { 554 String sTimePostfix( SVX_RES( RID_STR_POSTFIX_TIME ) ); 555 xCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sTimePostfix ) ) ); 556 557 String sDatePostfix( SVX_RES( RID_STR_POSTFIX_DATE ) ); 558 xSecondCol->setPropertyValue(FM_PROP_LABEL, makeAny( ::rtl::OUString( sFieldName + sDatePostfix ) ) ); 559 } 560 else 561 xCol->setPropertyValue(FM_PROP_LABEL, makeAny(sFieldName)); 562 563 FormControlFactory aControlFactory( ::comphelper::getProcessServiceFactory() ); 564 aControlFactory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xCol ); 565 aControlFactory.initializeFieldDependentProperties( xField, xCol, xNumberFormats ); 566 567 xCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName)); 568 if ( xSecondCol.is() ) 569 xSecondCol->setPropertyValue(FM_PROP_CONTROLSOURCE, makeAny(sFieldName)); 570 571 if (bDateNTimeCol) 572 { 573 String sRealName,sPurePostfix; 574 575 String aPostfix[] = { 576 String( SVX_RES( RID_STR_POSTFIX_DATE ) ), 577 String( SVX_RES( RID_STR_POSTFIX_TIME ) ) 578 }; 579 580 for ( size_t i=0; i<2; ++i ) 581 { 582 sPurePostfix = aPostfix[i]; 583 sPurePostfix.EraseLeadingChars(' '); 584 sPurePostfix.EraseLeadingChars('('); 585 sPurePostfix.EraseTrailingChars(')'); 586 sRealName = sFieldName; 587 sRealName += '_'; 588 sRealName += sPurePostfix; 589 if (i) 590 xSecondCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName))); 591 else 592 xCol->setPropertyValue(FM_PROP_NAME, makeAny(::rtl::OUString(sRealName))); 593 } 594 } 595 else 596 xCol->setPropertyValue(FM_PROP_NAME, makeAny(sFieldName)); 597 598 // jetzt einfuegen 599 Any aElement; 600 aElement <<= xCol; 601 xCols->insertByIndex(nPos, aElement); 602 603 if (bDateNTimeCol) 604 { 605 aElement <<= xSecondCol; 606 xCols->insertByIndex(nPos == (sal_uInt16)-1 ? nPos : ++nPos, aElement); 607 } 608 609 // ist die component::Form an die Datenbankangebunden? 610 Reference< XFormComponent > xFormCp(xCols, UNO_QUERY); 611 Reference< XPropertySet > xForm(xFormCp->getParent(), UNO_QUERY); 612 if (xForm.is()) 613 { 614 if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_DATASOURCE)).getLength()) 615 { 616 if ( sDatasouce.getLength() ) 617 xForm->setPropertyValue(FM_PROP_DATASOURCE, makeAny(sDatasouce)); 618 else 619 xForm->setPropertyValue(FM_PROP_URL, makeAny(sURL)); 620 } 621 622 if (!::comphelper::getString(xForm->getPropertyValue(FM_PROP_COMMAND)).getLength()) 623 { 624 xForm->setPropertyValue(FM_PROP_COMMAND, makeAny(sCommand)); 625 Any aCommandType; 626 switch (nCommandType) 627 { 628 case CommandType::TABLE: 629 aCommandType <<= (sal_Int32)CommandType::TABLE; 630 break; 631 case CommandType::QUERY: 632 aCommandType <<= (sal_Int32)CommandType::QUERY; 633 break; 634 default: 635 aCommandType <<= (sal_Int32)CommandType::COMMAND; 636 xForm->setPropertyValue(FM_PROP_ESCAPE_PROCESSING, bool2any((sal_Bool)(2 == nCommandType))); 637 break; 638 } 639 xForm->setPropertyValue(FM_PROP_COMMANDTYPE, aCommandType); 640 } 641 } 642 } 643 catch (Exception&) 644 { 645 DBG_ERROR("FmGridHeader::OnAsyncExecuteDrop: caught an exception while creatin' the column !"); 646 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); 647 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); 648 return 0L; 649 } 650 651 ::comphelper::disposeComponent(m_pImpl->xDroppedResultSet); 652 ::comphelper::disposeComponent(m_pImpl->xDroppedStatement); 653 return 1L; 654 } 655 656 //------------------------------------------------------------------------------ 657 void FmGridHeader::PreExecuteColumnContextMenu(sal_uInt16 nColId, PopupMenu& rMenu) 658 { 659 sal_Bool bDesignMode = static_cast<FmGridControl*>(GetParent())->IsDesignMode(); 660 661 Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); 662 // Aufbau des Insert Menues 663 // mark the column if nColId != HEADERBAR_ITEM_NOTFOUND 664 if(nColId > 0) 665 { 666 sal_uInt16 nPos2 = GetModelColumnPos(nColId); 667 668 Reference< ::com::sun::star::container::XIndexContainer > xColumns(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); 669 Reference< ::com::sun::star::beans::XPropertySet> xColumn; 670 ::cppu::extractInterface(xColumn, xColumns->getByIndex(nPos2)); 671 Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); 672 if (xSelSupplier.is()) 673 xSelSupplier->select(makeAny(xColumn)); 674 } 675 676 // EinfuegePosition, immer vor der aktuellen Spalte 677 sal_uInt16 nPos = GetModelColumnPos(nColId); 678 sal_Bool bMarked = nColId && static_cast<FmGridControl*>(GetParent())->isColumnMarked(nColId); 679 680 ImageList aImageList( SVX_RES(RID_SVXIMGLIST_FMEXPL) ); 681 PopupMenu* pControlMenu = new PopupMenu; 682 683 PopupMenu* pMenu = rMenu.GetPopupMenu(SID_FM_INSERTCOL); 684 if (pMenu) 685 { 686 SetMenuItem(aImageList, SID_FM_EDIT, pMenu, *pControlMenu, bDesignMode); 687 SetMenuItem(aImageList, SID_FM_CHECKBOX, pMenu, *pControlMenu, bDesignMode); 688 SetMenuItem(aImageList, SID_FM_COMBOBOX, pMenu, *pControlMenu, bDesignMode); 689 SetMenuItem(aImageList, SID_FM_LISTBOX, pMenu, *pControlMenu, bDesignMode); 690 SetMenuItem(aImageList, SID_FM_DATEFIELD, pMenu, *pControlMenu, bDesignMode); 691 SetMenuItem(aImageList, SID_FM_TIMEFIELD, pMenu, *pControlMenu, bDesignMode); 692 SetMenuItem(aImageList, SID_FM_NUMERICFIELD, pMenu, *pControlMenu, bDesignMode); 693 SetMenuItem(aImageList, SID_FM_CURRENCYFIELD, pMenu, *pControlMenu, bDesignMode); 694 SetMenuItem(aImageList, SID_FM_PATTERNFIELD, pMenu, *pControlMenu, bDesignMode); 695 SetMenuItem(aImageList, SID_FM_FORMATTEDFIELD, pMenu, *pControlMenu, bDesignMode); 696 } 697 698 if (pMenu && xCols.is() && nColId) 699 { 700 Reference< ::com::sun::star::beans::XPropertySet > xSet; 701 ::cppu::extractInterface(xSet, xCols->getByIndex(nPos)); 702 sal_Int16 nClassId; 703 xSet->getPropertyValue(FM_PROP_CLASSID) >>= nClassId; 704 705 Reference< ::com::sun::star::io::XPersistObject > xServiceQuestion(xSet, UNO_QUERY); 706 sal_Int32 nColType = xServiceQuestion.is() ? getColumnTypeByModelName(xServiceQuestion->getServiceName()) : 0; 707 if (nColType == TYPE_TEXTFIELD) 708 { // edit fields and formatted fields have the same service name, thus getColumnTypeByModelName returns TYPE_TEXTFIELD 709 // in both cases. And as columns don't have an ::com::sun::star::lang::XServiceInfo interface, we have to distinguish both 710 // types via the existence of special properties 711 Reference< ::com::sun::star::beans::XPropertySet > xProps(xSet, UNO_QUERY); 712 if (xProps.is()) 713 { 714 Reference< ::com::sun::star::beans::XPropertySetInfo > xPropsInfo = xProps->getPropertySetInfo(); 715 if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(FM_PROP_FORMATSSUPPLIER)) 716 nColType = TYPE_FORMATTEDFIELD; 717 } 718 } 719 720 pControlMenu->EnableItem(SID_FM_EDIT + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TEXTFIELD)); 721 pControlMenu->EnableItem(SID_FM_COMBOBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_COMBOBOX)); 722 pControlMenu->EnableItem(SID_FM_LISTBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_LISTBOX)); 723 pControlMenu->EnableItem(SID_FM_CHECKBOX + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CHECKBOX)); 724 pControlMenu->EnableItem(SID_FM_DATEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_DATEFIELD)); 725 pControlMenu->EnableItem(SID_FM_NUMERICFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_NUMERICFIELD)); 726 pControlMenu->EnableItem(SID_FM_TIMEFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_TIMEFIELD)); 727 pControlMenu->EnableItem(SID_FM_CURRENCYFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_CURRENCYFIELD)); 728 pControlMenu->EnableItem(SID_FM_PATTERNFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_PATTERNFIELD)); 729 pControlMenu->EnableItem(SID_FM_FORMATTEDFIELD + nChangeTypeOffset, bDesignMode && (nColType != TYPE_FORMATTEDFIELD)); 730 rMenu.SetPopupMenu(SID_FM_CHANGECOL, pControlMenu); 731 } 732 733 rMenu.EnableItem(SID_FM_INSERTCOL, bDesignMode && xCols.is()); 734 rMenu.EnableItem(SID_FM_DELETECOL, bDesignMode && bMarked && xCols.is()); 735 rMenu.EnableItem(SID_FM_CHANGECOL, bDesignMode && bMarked && xCols.is()); 736 rMenu.EnableItem(SID_FM_SHOW_PROPERTY_BROWSER, bDesignMode && bMarked && xCols.is()); 737 738 PopupMenu* pShowColsMenu = rMenu.GetPopupMenu(SID_FM_SHOWCOLS); 739 sal_uInt16 nHiddenCols = 0; 740 if (pShowColsMenu) 741 { 742 if (xCols.is()) 743 { 744 // check for hidden cols 745 Reference< ::com::sun::star::beans::XPropertySet > xCurCol; 746 Any aHidden,aName; 747 for (sal_uInt16 i=0; i<xCols->getCount(); ++i) 748 { 749 ::cppu::extractInterface(xCurCol, xCols->getByIndex(i)); 750 DBG_ASSERT(xCurCol.is(), "FmGridHeader::PreExecuteColumnContextMenu : the Peer has invalid columns !"); 751 aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN); 752 DBG_ASSERT(aHidden.getValueType().getTypeClass() == TypeClass_BOOLEAN, 753 "FmGridHeader::PreExecuteColumnContextMenu : the property 'hidden' should be boolean !"); 754 if (::comphelper::getBOOL(aHidden)) 755 { 756 // put the column name into the 'show col' menu 757 if (nHiddenCols < 16) 758 { // (only the first 16 items to keep the menu rather small) 759 aName = xCurCol->getPropertyValue(FM_PROP_LABEL); 760 pShowColsMenu->InsertItem(nHiddenCols + 1, ::comphelper::getString(aName), 0, nHiddenCols); 761 // the ID is arbitrary, but should be unique within the whole menu 762 } 763 ++nHiddenCols; 764 } 765 } 766 } 767 pShowColsMenu->EnableItem(SID_FM_SHOWCOLS_MORE, xCols.is() && (nHiddenCols > 16)); 768 pShowColsMenu->EnableItem(SID_FM_SHOWALLCOLS, xCols.is() && (nHiddenCols > 0)); 769 } 770 771 // allow the 'hide column' item ? 772 sal_Bool bAllowHide = bMarked; // a column is marked 773 bAllowHide = bAllowHide || (!bDesignMode && (nPos != (sal_uInt16)-1)); // OR we are in alive mode and have hit a column 774 bAllowHide = bAllowHide && xCols.is(); // AND we have a column container 775 bAllowHide = bAllowHide && (xCols->getCount()-nHiddenCols > 1); // AND there are at least two visible columns 776 rMenu.EnableItem(SID_FM_HIDECOL, bAllowHide); 777 778 sal_Bool bChecked = sal_False; 779 if (bMarked) 780 { 781 782 SfxViewFrame* pCurrentFrame = SfxViewFrame::Current(); 783 SfxItemState eState = SFX_ITEM_UNKNOWN; 784 // ask the bindings of the current view frame (which should be the one we're residing in) for the state 785 if (pCurrentFrame) 786 { 787 SfxPoolItem* pItem = NULL; 788 eState = pCurrentFrame->GetBindings().QueryState(SID_FM_CTL_PROPERTIES, pItem); 789 790 if (eState >= SFX_ITEM_AVAILABLE && pItem ) 791 { 792 bChecked = pItem->ISA(SfxBoolItem) && ((SfxBoolItem*)pItem)->GetValue(); 793 rMenu.CheckItem(SID_FM_SHOW_PROPERTY_BROWSER,bChecked); 794 } 795 delete pItem; 796 } 797 } 798 } 799 800 enum InspectorAction { eOpenInspector, eCloseInspector, eUpdateInspector, eNone }; 801 802 //------------------------------------------------------------------------------ 803 void FmGridHeader::PostExecuteColumnContextMenu(sal_uInt16 nColId, const PopupMenu& rMenu, sal_uInt16 nExecutionResult) 804 { 805 Reference< ::com::sun::star::container::XIndexContainer > xCols(static_cast<FmGridControl*>(GetParent())->GetPeer()->getColumns()); 806 sal_uInt16 nPos = GetModelColumnPos(nColId); 807 808 // remove and delet the menu we inserted in PreExecuteColumnContextMenu 809 PopupMenu* pControlMenu = rMenu.GetPopupMenu(SID_FM_CHANGECOL); 810 delete pControlMenu; 811 812 ::rtl::OUString aFieldType; 813 sal_Bool bReplace = sal_False; 814 InspectorAction eInspectorAction = eNone; 815 Reference< XPropertySet > xColumnToInspect; 816 switch (nExecutionResult) 817 { 818 case SID_FM_DELETECOL: 819 { 820 Reference< XInterface > xCol; 821 ::cppu::extractInterface(xCol, xCols->getByIndex(nPos)); 822 xCols->removeByIndex(nPos); 823 ::comphelper::disposeComponent(xCol); 824 } break; 825 case SID_FM_SHOW_PROPERTY_BROWSER: 826 eInspectorAction = rMenu.IsItemChecked( SID_FM_SHOW_PROPERTY_BROWSER ) ? eOpenInspector : eCloseInspector; 827 xColumnToInspect.set( xCols->getByIndex( nPos ), UNO_QUERY ); 828 break; 829 case SID_FM_EDIT + nChangeTypeOffset: 830 bReplace = sal_True; 831 case SID_FM_EDIT: 832 aFieldType = FM_COL_TEXTFIELD; 833 break; 834 case SID_FM_COMBOBOX + nChangeTypeOffset: 835 bReplace = sal_True; 836 case SID_FM_COMBOBOX: 837 aFieldType = FM_COL_COMBOBOX; 838 break; 839 case SID_FM_LISTBOX + nChangeTypeOffset: 840 bReplace = sal_True; 841 case SID_FM_LISTBOX: 842 aFieldType = FM_COL_LISTBOX; 843 break; 844 case SID_FM_CHECKBOX + nChangeTypeOffset: 845 bReplace = sal_True; 846 case SID_FM_CHECKBOX: 847 aFieldType = FM_COL_CHECKBOX; 848 break; 849 case SID_FM_DATEFIELD + nChangeTypeOffset: 850 bReplace = sal_True; 851 case SID_FM_DATEFIELD: 852 aFieldType = FM_COL_DATEFIELD; 853 break; 854 case SID_FM_TIMEFIELD + nChangeTypeOffset: 855 bReplace = sal_True; 856 case SID_FM_TIMEFIELD: 857 aFieldType = FM_COL_TIMEFIELD; 858 break; 859 case SID_FM_NUMERICFIELD + nChangeTypeOffset: 860 bReplace = sal_True; 861 case SID_FM_NUMERICFIELD: 862 aFieldType = FM_COL_NUMERICFIELD; 863 break; 864 case SID_FM_CURRENCYFIELD + nChangeTypeOffset: 865 bReplace = sal_True; 866 case SID_FM_CURRENCYFIELD: 867 aFieldType = FM_COL_CURRENCYFIELD; 868 break; 869 case SID_FM_PATTERNFIELD + nChangeTypeOffset: 870 bReplace = sal_True; 871 case SID_FM_PATTERNFIELD: 872 aFieldType = FM_COL_PATTERNFIELD; 873 break; 874 case SID_FM_FORMATTEDFIELD + nChangeTypeOffset: 875 bReplace = sal_True; 876 case SID_FM_FORMATTEDFIELD: 877 aFieldType = FM_COL_FORMATTEDFIELD; 878 break; 879 case SID_FM_HIDECOL: 880 { 881 Reference< ::com::sun::star::beans::XPropertySet > xCurCol; 882 ::cppu::extractInterface(xCurCol, xCols->getByIndex(nPos)); 883 xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_True)); 884 } 885 break; 886 case SID_FM_SHOWCOLS_MORE: 887 { 888 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); 889 if(pFact) 890 { 891 AbstractFmShowColsDialog* pDlg = pFact->CreateFmShowColsDialog(NULL); 892 DBG_ASSERT(pDlg, "Dialogdiet fail!");//CHINA001 893 pDlg->SetColumns(xCols); 894 pDlg->Execute(); 895 delete pDlg; 896 } 897 898 } 899 break; 900 case SID_FM_SHOWALLCOLS: 901 { 902 // just iterate through all the cols ... 903 Reference< ::com::sun::star::beans::XPropertySet > xCurCol; 904 for (sal_uInt16 i=0; i<xCols->getCount(); ++i) 905 { 906 ::cppu::extractInterface(xCurCol, xCols->getByIndex(i)); 907 xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False)); 908 } 909 // TODO : there must be a more clever way to do this .... 910 // with the above the view is updated after every single model update ... 911 } 912 break; 913 default: 914 if (nExecutionResult>0 && nExecutionResult<=16) 915 { // it was a "show column/<colname>" command (there are at most 16 such items) 916 // search the nExecutionResult'th hidden col 917 Reference< ::com::sun::star::beans::XPropertySet > xCurCol; 918 for (sal_uInt16 i=0; i<xCols->getCount() && nExecutionResult; ++i) 919 { 920 ::cppu::extractInterface(xCurCol, xCols->getByIndex(i)); 921 Any aHidden = xCurCol->getPropertyValue(FM_PROP_HIDDEN); 922 if (::comphelper::getBOOL(aHidden)) 923 if (!--nExecutionResult) 924 { 925 xCurCol->setPropertyValue(FM_PROP_HIDDEN, makeAny((sal_Bool)sal_False)); 926 break; 927 } 928 } 929 } 930 break; 931 } 932 933 if ( aFieldType.getLength() ) 934 { 935 try 936 { 937 Reference< XGridColumnFactory > xFactory( xCols, UNO_QUERY_THROW ); 938 Reference< XPropertySet > xNewCol( xFactory->createColumn( aFieldType ), UNO_SET_THROW ); 939 940 if ( bReplace ) 941 { 942 // ein paar Properties hinueberretten 943 Reference< XPropertySet > xReplaced( xCols->getByIndex( nPos ), UNO_QUERY ); 944 945 OStaticDataAccessTools().TransferFormComponentProperties( 946 xReplaced, xNewCol, Application::GetSettings().GetUILocale() ); 947 948 xCols->replaceByIndex( nPos, makeAny( xNewCol ) ); 949 ::comphelper::disposeComponent( xReplaced ); 950 951 eInspectorAction = eUpdateInspector; 952 xColumnToInspect = xNewCol; 953 } 954 else 955 { 956 FormControlFactory factory( ::comphelper::getProcessServiceFactory() ); 957 958 ::rtl::OUString sLabel = factory.getDefaultUniqueName_ByComponentType( 959 Reference< XNameAccess >( xCols, UNO_QUERY_THROW ), xNewCol ); 960 xNewCol->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel ) ); 961 xNewCol->setPropertyValue( FM_PROP_NAME, makeAny( sLabel ) ); 962 963 factory.initializeControlModel( DocumentClassification::classifyHostDocument( xCols ), xNewCol ); 964 965 xCols->insertByIndex( nPos, makeAny( xNewCol ) ); 966 } 967 } 968 catch( const Exception& ) 969 { 970 DBG_UNHANDLED_EXCEPTION(); 971 } 972 } 973 974 SfxViewFrame* pCurrentFrame = SfxViewFrame::Current(); 975 OSL_ENSURE( pCurrentFrame, "FmGridHeader::PostExecuteColumnContextMenu: no view frame -> no bindings -> no property browser!" ); 976 if ( pCurrentFrame ) 977 { 978 if ( eInspectorAction == eUpdateInspector ) 979 { 980 if ( !pCurrentFrame->HasChildWindow( SID_FM_SHOW_PROPERTIES ) ) 981 eInspectorAction = eNone; 982 } 983 984 if ( eInspectorAction != eNone ) 985 { 986 FmInterfaceItem aIFaceItem( SID_FM_SHOW_PROPERTY_BROWSER, xColumnToInspect ); 987 SfxBoolItem aShowItem( SID_FM_SHOW_PROPERTIES, eInspectorAction == eCloseInspector ? sal_False : sal_True ); 988 989 pCurrentFrame->GetBindings().GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON, 990 &aIFaceItem, &aShowItem, 0L ); 991 } 992 } 993 } 994 995 //------------------------------------------------------------------------------ 996 void FmGridHeader::triggerColumnContextMenu( const ::Point& _rPreferredPos ) 997 { 998 // the affected col 999 sal_uInt16 nColId = GetItemId( _rPreferredPos ); 1000 1001 // the menu 1002 PopupMenu aContextMenu( SVX_RES( RID_SVXMNU_COLS ) ); 1003 1004 // let derivees modify the menu 1005 PreExecuteColumnContextMenu( nColId, aContextMenu ); 1006 aContextMenu.RemoveDisabledEntries( sal_True, sal_True ); 1007 1008 // execute the menu 1009 sal_uInt16 nResult = aContextMenu.Execute( this, _rPreferredPos ); 1010 1011 // let derivees handle the result 1012 PostExecuteColumnContextMenu( nColId, aContextMenu, nResult ); 1013 } 1014 1015 //------------------------------------------------------------------------------ 1016 void FmGridHeader::Command(const CommandEvent& rEvt) 1017 { 1018 switch (rEvt.GetCommand()) 1019 { 1020 case COMMAND_CONTEXTMENU: 1021 { 1022 if (!rEvt.IsMouseEvent()) 1023 return; 1024 1025 triggerColumnContextMenu( rEvt.GetMousePosPixel() ); 1026 } 1027 break; 1028 default: 1029 EditBrowserHeader::Command(rEvt); 1030 } 1031 } 1032 1033 //------------------------------------------------------------------------------ 1034 FmGridControl::FmGridControl( 1035 Reference< ::com::sun::star::lang::XMultiServiceFactory > _rxFactory, 1036 Window* pParent, 1037 FmXGridPeer* _pPeer, 1038 WinBits nBits) 1039 :DbGridControl(_rxFactory, pParent, nBits) 1040 ,m_pPeer(_pPeer) 1041 ,m_nCurrentSelectedColumn(-1) 1042 ,m_nMarkedColumnId(BROWSER_INVALIDID) 1043 ,m_bSelecting(sal_False) 1044 ,m_bInColumnMove(sal_False) 1045 { 1046 EnableInteractiveRowHeight( ); 1047 } 1048 1049 //------------------------------------------------------------------------------ 1050 void FmGridControl::Command(const CommandEvent& _rEvt) 1051 { 1052 if ( COMMAND_CONTEXTMENU == _rEvt.GetCommand() ) 1053 { 1054 FmGridHeader* pMyHeader = static_cast< FmGridHeader* >( GetHeaderBar() ); 1055 if ( pMyHeader && !_rEvt.IsMouseEvent() ) 1056 { // context menu requested by keyboard 1057 if ( 1 == GetSelectColumnCount() || IsDesignMode() ) 1058 { 1059 sal_uInt16 nSelId = GetColumnId( 1060 sal::static_int_cast< sal_uInt16 >( FirstSelectedColumn() ) ); 1061 ::Rectangle aColRect( GetFieldRectPixel( 0, nSelId, sal_False ) ); 1062 1063 Point aRelativePos( pMyHeader->ScreenToOutputPixel( OutputToScreenPixel( aColRect.TopCenter() ) ) ); 1064 pMyHeader->triggerColumnContextMenu( aRelativePos, FmGridHeader::AccessControl() ); 1065 1066 // handled 1067 return; 1068 } 1069 } 1070 } 1071 1072 DbGridControl::Command( _rEvt ); 1073 } 1074 1075 // ::com::sun::star::beans::XPropertyChangeListener 1076 //------------------------------------------------------------------------------ 1077 void FmGridControl::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) 1078 { 1079 if (evt.PropertyName == FM_PROP_ROWCOUNT) 1080 { 1081 // if we're not in the main thread call AdjustRows asynchronously 1082 implAdjustInSolarThread(sal_True); 1083 return; 1084 } 1085 1086 const DbGridRowRef& xRow = GetCurrentRow(); 1087 // waehrend Positionierung wird kein abgleich der Properties vorgenommen 1088 Reference<XPropertySet> xSet(evt.Source,UNO_QUERY); 1089 if (xRow.Is() && (::cppu::any2bool(xSet->getPropertyValue(FM_PROP_ISNEW))|| CompareBookmark(getDataSource()->getBookmark(), xRow->GetBookmark()))) 1090 { 1091 if (evt.PropertyName == FM_PROP_ISMODIFIED) 1092 { 1093 // modified or clean ? 1094 GridRowStatus eStatus = ::comphelper::getBOOL(evt.NewValue) ? GRS_MODIFIED : GRS_CLEAN; 1095 if (eStatus != xRow->GetStatus()) 1096 { 1097 xRow->SetStatus(eStatus); 1098 vos::OGuard aGuard( Application::GetSolarMutex() ); 1099 RowModified(GetCurrentPos()); 1100 } 1101 } 1102 } 1103 } 1104 1105 //------------------------------------------------------------------------------ 1106 void FmGridControl::SetDesignMode(sal_Bool bMode) 1107 { 1108 sal_Bool bOldMode = IsDesignMode(); 1109 DbGridControl::SetDesignMode(bMode); 1110 if (bOldMode != bMode) 1111 { 1112 if (!bMode) 1113 { 1114 // selection aufheben 1115 markColumn(USHRT_MAX); 1116 } 1117 else 1118 { 1119 Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns()); 1120 Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); 1121 if (xSelSupplier.is()) 1122 { 1123 Any aSelection = xSelSupplier->getSelection(); 1124 Reference< ::com::sun::star::beans::XPropertySet > xColumn; 1125 if (aSelection.getValueType().getTypeClass() == TypeClass_INTERFACE) 1126 ::cppu::extractInterface(xColumn, aSelection); 1127 Reference< XInterface > xCurrent; 1128 for (sal_uInt16 i=0; i<xColumns->getCount(); ++i) 1129 { 1130 ::cppu::extractInterface(xCurrent, xColumns->getByIndex(i)); 1131 if (xCurrent == xColumn) 1132 { 1133 markColumn(GetColumnIdFromModelPos(i)); 1134 break; 1135 } 1136 } 1137 } 1138 } 1139 } 1140 } 1141 1142 //------------------------------------------------------------------------------ 1143 void FmGridControl::DeleteSelectedRows() 1144 { 1145 if (!m_pSeekCursor) 1146 return; 1147 1148 // how many rows are selected? 1149 sal_Int32 nSelectedRows = GetSelectRowCount(); 1150 1151 // the current line should be deleted but it is currently in edit mode 1152 if ( IsCurrentAppending() ) 1153 return; 1154 // is the insert row selected 1155 if (GetEmptyRow().Is() && IsRowSelected(GetRowCount() - 1)) 1156 nSelectedRows -= 1; 1157 1158 // nothing to do 1159 if (nSelectedRows <= 0) 1160 return; 1161 1162 // try to confirm the delete 1163 Reference< ::com::sun::star::frame::XDispatchProvider > xDispatcher = (::com::sun::star::frame::XDispatchProvider*)GetPeer(); 1164 if (xDispatcher.is()) 1165 { 1166 ::com::sun::star::util::URL aUrl; 1167 aUrl.Complete = FMURL_CONFIRM_DELETION; 1168 // #100312# ------------ 1169 Reference< ::com::sun::star::util::XURLTransformer > xTransformer( 1170 ::comphelper::getProcessServiceFactory()->createInstance( 1171 ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")), UNO_QUERY); 1172 if( xTransformer.is() ) 1173 xTransformer->parseStrict( aUrl ); 1174 1175 Reference< ::com::sun::star::frame::XDispatch > xDispatch = xDispatcher->queryDispatch(aUrl, rtl::OUString(), 0); 1176 Reference< ::com::sun::star::form::XConfirmDeleteListener > xConfirm(xDispatch, UNO_QUERY); 1177 if (xConfirm.is()) 1178 { 1179 ::com::sun::star::sdb::RowChangeEvent aEvent; 1180 aEvent.Source = (Reference< XInterface > )(*getDataSource()); 1181 aEvent.Rows = nSelectedRows; 1182 aEvent.Action = ::com::sun::star::sdb::RowChangeAction::DELETE; 1183 if (!xConfirm->confirmDelete(aEvent)) 1184 return; 1185 } 1186 } 1187 1188 const MultiSelection* pRowSelection = GetSelection(); 1189 if ( pRowSelection && pRowSelection->IsAllSelected() ) 1190 { 1191 BeginCursorAction(); 1192 CursorWrapper* pCursor = getDataSource(); 1193 Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*pCursor, UNO_QUERY); 1194 try 1195 { 1196 pCursor->beforeFirst(); 1197 while( pCursor->next() ) 1198 xUpdateCursor->deleteRow(); 1199 1200 SetUpdateMode(sal_False); 1201 SetNoSelection(); 1202 1203 xUpdateCursor->moveToInsertRow(); 1204 } 1205 catch(const Exception&) 1206 { 1207 OSL_ENSURE(0,"Exception caught while deleting rows!"); 1208 } 1209 // An den DatenCursor anpassen 1210 AdjustDataSource(sal_True); 1211 EndCursorAction(); 1212 SetUpdateMode(sal_True); 1213 } 1214 else 1215 { 1216 Reference< ::com::sun::star::sdbcx::XDeleteRows > xDeleteThem((Reference< XInterface >)*getDataSource(), UNO_QUERY); 1217 1218 // colect the bookmarks of the selected rows 1219 Sequence < Any> aBookmarks = getSelectionBookmarks(); 1220 1221 // determine the next row to position after deletion 1222 Any aBookmark; 1223 sal_Bool bNewPos = sal_False; 1224 // if the current row isn't selected we take the row as row after deletion 1225 OSL_ENSURE( GetCurrentRow().Is(), "FmGridControl::DeleteSelectedRows: no current row here?" ); 1226 // crash reports suggest it can happen we don't have a current row - how? 1227 // #154303# / 2008-04-23 / frank.schoenheit@sun.com 1228 if ( !IsRowSelected( GetCurrentPos() ) && !IsCurrentAppending() && GetCurrentRow().Is() ) 1229 { 1230 aBookmark = GetCurrentRow()->GetBookmark(); 1231 bNewPos = sal_True; 1232 } 1233 else 1234 { 1235 // we look for the first row after the selected block for selection 1236 long nIdx = LastSelectedRow() + 1; 1237 if (nIdx < GetRowCount() - 1) 1238 { 1239 // there is a next row to position on 1240 if (SeekCursor(nIdx)) 1241 { 1242 GetSeekRow()->SetState(m_pSeekCursor, sal_True); 1243 1244 bNewPos = sal_True; 1245 // if it's not the row for inserting we keep the bookmark 1246 if (!IsInsertionRow(nIdx)) 1247 aBookmark = m_pSeekCursor->getBookmark(); 1248 } 1249 } 1250 else 1251 { 1252 // we look for the first row before the selected block for selection after deletion 1253 nIdx = FirstSelectedRow() - 1; 1254 if (nIdx >= 0 && SeekCursor(nIdx)) 1255 { 1256 GetSeekRow()->SetState(m_pSeekCursor, sal_True); 1257 1258 bNewPos = sal_True; 1259 aBookmark = m_pSeekCursor->getBookmark(); 1260 } 1261 } 1262 } 1263 1264 // Sind alle Zeilen Selectiert 1265 // Zweite bedingung falls keine einguegeZeile existiert 1266 sal_Bool bAllSelected = GetTotalCount() == nSelectedRows || GetRowCount() == nSelectedRows; 1267 1268 BeginCursorAction(); 1269 1270 // now delete the row 1271 Sequence <sal_Int32> aDeletedRows; 1272 SetUpdateMode( sal_False ); 1273 try 1274 { 1275 aDeletedRows = xDeleteThem->deleteRows(aBookmarks); 1276 } 1277 catch(SQLException&) 1278 { 1279 } 1280 SetUpdateMode( sal_True ); 1281 1282 // how many rows are deleted? 1283 sal_Int32 nDeletedRows = 0; 1284 const sal_Int32* pSuccess = aDeletedRows.getConstArray(); 1285 for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++) 1286 { 1287 if (pSuccess[i]) 1288 ++nDeletedRows; 1289 } 1290 1291 // sind Zeilen geloescht worden? 1292 if (nDeletedRows) 1293 { 1294 SetUpdateMode(sal_False); 1295 SetNoSelection(); 1296 try 1297 { 1298 // did we delete all the rows than try to move to the next possible row 1299 if (nDeletedRows == aDeletedRows.getLength()) 1300 { 1301 // there exists a new position to move on 1302 if (bNewPos) 1303 { 1304 if (aBookmark.hasValue()) 1305 getDataSource()->moveToBookmark(aBookmark); 1306 // no valid bookmark so move to the insert row 1307 else 1308 { 1309 Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY); 1310 xUpdateCursor->moveToInsertRow(); 1311 } 1312 } 1313 else 1314 { 1315 Reference< ::com::sun::star::beans::XPropertySet > xSet((Reference< XInterface >)*m_pDataCursor, UNO_QUERY); 1316 1317 sal_Int32 nRecordCount(0); 1318 xSet->getPropertyValue(FM_PROP_ROWCOUNT) >>= nRecordCount; 1319 if ( m_pDataCursor->rowDeleted() ) 1320 --nRecordCount; 1321 1322 // there are no rows left and we have an insert row 1323 if (!nRecordCount && GetEmptyRow().Is()) 1324 { 1325 Reference< XResultSetUpdate > xUpdateCursor((Reference< XInterface >)*m_pDataCursor, UNO_QUERY); 1326 xUpdateCursor->moveToInsertRow(); 1327 } 1328 else if (nRecordCount) 1329 // move to the first row 1330 getDataSource()->first(); 1331 } 1332 } 1333 // not all the rows where deleted, so move to the first row which remained in the resultset 1334 else 1335 { 1336 for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++) 1337 { 1338 if (!pSuccess[i]) 1339 { 1340 getDataSource()->moveToBookmark(aBookmarks.getConstArray()[i]); 1341 break; 1342 } 1343 } 1344 } 1345 } 1346 catch(const Exception&) 1347 { 1348 try 1349 { 1350 // positioning went wrong so try to move to the first row 1351 getDataSource()->first(); 1352 } 1353 catch(const Exception&) 1354 { 1355 } 1356 } 1357 1358 // An den DatenCursor anpassen 1359 AdjustDataSource(sal_True); 1360 1361 // es konnten nicht alle Zeilen geloescht werden 1362 // da nie nicht geloeschten wieder selektieren 1363 if (nDeletedRows < nSelectedRows) 1364 { 1365 // waren alle selektiert 1366 if (bAllSelected) 1367 { 1368 SelectAll(); 1369 if (IsInsertionRow(GetRowCount() - 1)) // einfuegeZeile nicht 1370 SelectRow(GetRowCount() - 1, sal_False); 1371 } 1372 else 1373 { 1374 // select the remaining rows 1375 for (sal_Int32 i = 0; i < aDeletedRows.getLength(); i++) 1376 { 1377 try 1378 { 1379 if (!pSuccess[i]) 1380 { 1381 m_pSeekCursor->moveToBookmark(m_pDataCursor->getBookmark()); 1382 SetSeekPos(m_pSeekCursor->getRow() - 1); 1383 SelectRow(GetSeekPos()); 1384 } 1385 } 1386 catch(const Exception&) 1387 { 1388 // keep the seekpos in all cases 1389 SetSeekPos(m_pSeekCursor->getRow() - 1); 1390 } 1391 } 1392 } 1393 } 1394 1395 EndCursorAction(); 1396 SetUpdateMode(sal_True); 1397 } 1398 else // Zeile konnte nicht geloescht werden 1399 { 1400 EndCursorAction(); 1401 try 1402 { 1403 // currentrow is the insert row? 1404 if (!IsCurrentAppending()) 1405 getDataSource()->refreshRow(); 1406 } 1407 catch(const Exception&) 1408 { 1409 } 1410 } 1411 } 1412 1413 // if there is no selection anymore we can start editing 1414 if (!GetSelectRowCount()) 1415 ActivateCell(); 1416 } 1417 1418 1419 // XCurrentRecordListener 1420 //------------------------------------------------------------------------------ 1421 void FmGridControl::positioned(const ::com::sun::star::lang::EventObject& /*rEvent*/) 1422 { 1423 TRACE_RANGE("FmGridControl::positioned"); 1424 // position on the data source (force it to be done in the main thread) 1425 implAdjustInSolarThread(sal_False); 1426 } 1427 1428 //------------------------------------------------------------------------------ 1429 sal_Bool FmGridControl::commit() 1430 { 1431 // Commit nur ausfuehren, wenn nicht bereits ein Update vom ::com::sun::star::form::component::GridControl ausgefuehrt 1432 // wird 1433 if (!IsUpdating()) 1434 { 1435 if (Controller().Is() && Controller()->IsModified()) 1436 { 1437 if (!SaveModified()) 1438 return sal_False; 1439 } 1440 } 1441 return sal_True; 1442 } 1443 1444 //------------------------------------------------------------------------------ 1445 void FmGridControl::inserted(const ::com::sun::star::lang::EventObject& /*rEvent*/) 1446 { 1447 const DbGridRowRef& xRow = GetCurrentRow(); 1448 if (!xRow.Is()) 1449 return; 1450 1451 // Zeile ist eingefuegt worden, dann den status und mode zuruecksetzen 1452 xRow->SetState(m_pDataCursor, sal_False); 1453 xRow->SetNew(sal_False); 1454 1455 } 1456 1457 // XCancelUpdateRecordListener 1458 //------------------------------------------------------------------------------ 1459 void FmGridControl::restored(const ::com::sun::star::lang::EventObject& rEvent) 1460 { 1461 if (!GetCurrentRow().Is()) 1462 return; 1463 1464 sal_Bool bAppending = GetCurrentRow()->IsNew(); 1465 sal_Bool bDirty = GetCurrentRow()->IsModified(); 1466 if (bAppending && (EditBrowseBox::IsModified() || bDirty)) 1467 { 1468 if (Controller().Is()) 1469 Controller()->ClearModified(); 1470 1471 // jetzt die Zeile herausnehmen 1472 RowRemoved(GetRowCount() - 1, 1, sal_True); 1473 GetNavigationBar().InvalidateAll(); 1474 } 1475 1476 positioned(rEvent); 1477 } 1478 1479 //------------------------------------------------------------------------------ 1480 BrowserHeader* FmGridControl::imp_CreateHeaderBar(BrowseBox* pParent) 1481 { 1482 DBG_ASSERT( pParent == this, "FmGridControl::imp_CreateHeaderBar: parent?" ); 1483 return new FmGridHeader( pParent ); 1484 } 1485 1486 //------------------------------------------------------------------------------ 1487 void FmGridControl::markColumn(sal_uInt16 nId) 1488 { 1489 if (GetHeaderBar() && m_nMarkedColumnId != nId) 1490 { 1491 // deselektieren 1492 if (m_nMarkedColumnId != BROWSER_INVALIDID) 1493 { 1494 HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(m_nMarkedColumnId) & ~HIB_FLAT; 1495 GetHeaderBar()->SetItemBits(m_nMarkedColumnId, aBits); 1496 } 1497 1498 1499 if (nId != BROWSER_INVALIDID) 1500 { 1501 HeaderBarItemBits aBits = GetHeaderBar()->GetItemBits(nId) | HIB_FLAT; 1502 GetHeaderBar()->SetItemBits(nId, aBits); 1503 } 1504 m_nMarkedColumnId = nId; 1505 } 1506 } 1507 1508 //------------------------------------------------------------------------------ 1509 sal_Bool FmGridControl::isColumnMarked(sal_uInt16 nId) const 1510 { 1511 return m_nMarkedColumnId == nId; 1512 } 1513 1514 //------------------------------------------------------------------------------ 1515 long FmGridControl::QueryMinimumRowHeight() 1516 { 1517 long nMinimalLogicHeight = 20; // 0.2 cm 1518 long nMinimalPixelHeight = LogicToPixel( Point( 0, nMinimalLogicHeight ), MAP_10TH_MM ).Y(); 1519 return CalcZoom( nMinimalPixelHeight ); 1520 } 1521 1522 //------------------------------------------------------------------------------ 1523 void FmGridControl::RowHeightChanged() 1524 { 1525 DbGridControl::RowHeightChanged(); 1526 1527 Reference< XPropertySet > xModel( GetPeer()->getColumns(), UNO_QUERY ); 1528 DBG_ASSERT( xModel.is(), "FmGridControl::RowHeightChanged: no model!" ); 1529 if ( xModel.is() ) 1530 { 1531 try 1532 { 1533 sal_Int32 nUnzoomedPixelHeight = CalcReverseZoom( GetDataRowHeight() ); 1534 Any aProperty = makeAny( (sal_Int32)PixelToLogic( Point( 0, nUnzoomedPixelHeight ), MAP_10TH_MM ).Y() ); 1535 xModel->setPropertyValue( FM_PROP_ROWHEIGHT, aProperty ); 1536 } 1537 catch( const Exception& ) 1538 { 1539 OSL_ENSURE( sal_False, "FmGridControl::RowHeightChanged: caught an exception!" ); 1540 } 1541 } 1542 } 1543 1544 //------------------------------------------------------------------------------ 1545 void FmGridControl::ColumnResized(sal_uInt16 nId) 1546 { 1547 DbGridControl::ColumnResized(nId); 1548 1549 // Wert ans model uebergeben 1550 DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId)); 1551 Reference< ::com::sun::star::beans::XPropertySet > xColModel(pCol->getModel()); 1552 if (xColModel.is()) 1553 { 1554 Any aWidth; 1555 sal_Int32 nColumnWidth = GetColumnWidth(nId); 1556 nColumnWidth = CalcReverseZoom(nColumnWidth); 1557 // Umrechnen in 10THMM 1558 aWidth <<= (sal_Int32)PixelToLogic(Point(nColumnWidth,0),MAP_10TH_MM).X(); 1559 xColModel->setPropertyValue(FM_PROP_WIDTH, aWidth); 1560 } 1561 } 1562 1563 //------------------------------------------------------------------------------ 1564 void FmGridControl::CellModified() 1565 { 1566 DbGridControl::CellModified(); 1567 GetPeer()->CellModified(); 1568 } 1569 1570 //------------------------------------------------------------------------------ 1571 void FmGridControl::BeginCursorAction() 1572 { 1573 DbGridControl::BeginCursorAction(); 1574 m_pPeer->stopCursorListening(); 1575 } 1576 1577 //------------------------------------------------------------------------------ 1578 void FmGridControl::EndCursorAction() 1579 { 1580 m_pPeer->startCursorListening(); 1581 DbGridControl::EndCursorAction(); 1582 } 1583 1584 //------------------------------------------------------------------------------ 1585 void FmGridControl::ColumnMoved(sal_uInt16 nId) 1586 { 1587 m_bInColumnMove = sal_True; 1588 1589 DbGridControl::ColumnMoved(nId); 1590 Reference< ::com::sun::star::container::XIndexContainer > xColumns(GetPeer()->getColumns()); 1591 1592 if (xColumns.is()) 1593 { 1594 // suchen der Spalte und verschieben im Model 1595 // ColumnPos holen 1596 DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(GetModelColumnPos(nId)); 1597 Reference< ::com::sun::star::beans::XPropertySet > xCol; 1598 1599 // Einfuegen muß sich an den Column Positionen orientieren 1600 sal_Int32 i; 1601 Reference< XInterface > xCurrent; 1602 for (i = 0; !xCol.is() && i < xColumns->getCount(); i++) 1603 { 1604 ::cppu::extractInterface(xCurrent, xColumns->getByIndex(i)); 1605 if (xCurrent == pCol->getModel()) 1606 { 1607 xCol = pCol->getModel(); 1608 break; 1609 } 1610 } 1611 1612 DBG_ASSERT(i < xColumns->getCount(), "Falscher ::com::sun::star::sdbcx::Index"); 1613 xColumns->removeByIndex(i); 1614 Any aElement; 1615 aElement <<= xCol; 1616 xColumns->insertByIndex(GetModelColumnPos(nId), aElement); 1617 pCol->setModel(xCol); 1618 // if the column which is shown here is selected ... 1619 if ( isColumnSelected(nId,pCol) ) 1620 markColumn(nId); // ... -> mark it 1621 } 1622 1623 m_bInColumnMove = sal_False; 1624 } 1625 1626 //------------------------------------------------------------------------------ 1627 void FmGridControl::InitColumnsByModels(const Reference< ::com::sun::star::container::XIndexContainer >& xColumns) 1628 { 1629 // Spalten wieder neu setzen 1630 // wenn es nur eine HandleColumn gibt, dann nicht 1631 if (GetModelColCount()) 1632 { 1633 RemoveColumns(); 1634 InsertHandleColumn(); 1635 } 1636 1637 if (!xColumns.is()) 1638 return; 1639 1640 SetUpdateMode(sal_False); 1641 1642 // Einfuegen mu� sich an den Column Positionen orientieren 1643 sal_Int32 i; 1644 String aName; 1645 Any aWidth; 1646 for (i = 0; i < xColumns->getCount(); ++i) 1647 { 1648 Reference< ::com::sun::star::beans::XPropertySet > xCol; 1649 ::cppu::extractInterface(xCol, xColumns->getByIndex(i)); 1650 1651 aName = ::comphelper::getString( xCol->getPropertyValue(FM_PROP_LABEL)).getStr(); 1652 1653 aWidth = xCol->getPropertyValue(FM_PROP_WIDTH); 1654 sal_Int32 nWidth = 0; 1655 if (aWidth >>= nWidth) 1656 nWidth = LogicToPixel(Point(nWidth,0),MAP_10TH_MM).X(); 1657 1658 AppendColumn(aName, (sal_uInt16)nWidth); 1659 DbGridColumn* pCol = DbGridControl::GetColumns().GetObject(i); 1660 pCol->setModel(xCol); 1661 } 1662 1663 // und jetzt noch die hidden columns rausnehmen 1664 // (wir haben das nicht gleich in der oberen Schleife gemacht, da wir dann Probleme mit den 1665 // IDs der Spalten bekommen haetten : AppendColumn vergibt die automatisch, die Spalte _nach_ 1666 // einer versteckten braucht aber eine um eine erhoehte ID .... 1667 Any aHidden; 1668 for (i = 0; i < xColumns->getCount(); ++i) 1669 { 1670 Reference< ::com::sun::star::beans::XPropertySet > xCol; 1671 ::cppu::extractInterface(xCol, xColumns->getByIndex(i)); 1672 aHidden = xCol->getPropertyValue(FM_PROP_HIDDEN); 1673 if (::comphelper::getBOOL(aHidden)) 1674 HideColumn(GetColumnIdFromModelPos((sal_uInt16)i)); 1675 } 1676 1677 SetUpdateMode(sal_True); 1678 } 1679 1680 //------------------------------------------------------------------------------ 1681 void FmGridControl::InitColumnByField( 1682 DbGridColumn* _pColumn, const Reference< XPropertySet >& _rxColumnModel, 1683 const Reference< XNameAccess >& _rxFieldsByNames, const Reference< XIndexAccess >& _rxFieldsByIndex ) 1684 { 1685 DBG_ASSERT( _rxFieldsByNames == _rxFieldsByIndex, "FmGridControl::InitColumnByField: invalid container interfaces!" ); 1686 1687 // lookup the column which belongs to the control source 1688 ::rtl::OUString sFieldName; 1689 _rxColumnModel->getPropertyValue( FM_PROP_CONTROLSOURCE ) >>= sFieldName; 1690 Reference< XPropertySet > xField; 1691 _rxColumnModel->getPropertyValue( FM_PROP_BOUNDFIELD ) >>= xField; 1692 1693 1694 if ( !xField.is() && /*sFieldName.getLength() && */_rxFieldsByNames->hasByName( sFieldName ) ) // #i93452# do not check for name length 1695 _rxFieldsByNames->getByName( sFieldName ) >>= xField; 1696 1697 // determine the position of this column 1698 sal_Int32 nFieldPos = -1; 1699 if ( xField.is() ) 1700 { 1701 Reference< XPropertySet > xCheck; 1702 sal_Int32 nFieldCount = _rxFieldsByIndex->getCount(); 1703 for ( sal_Int32 i = 0; i < nFieldCount; ++i) 1704 { 1705 _rxFieldsByIndex->getByIndex( i ) >>= xCheck; 1706 if ( xField.get() == xCheck.get() ) 1707 { 1708 nFieldPos = i; 1709 break; 1710 } 1711 } 1712 } 1713 1714 if ( xField.is() && ( nFieldPos >= 0 ) ) 1715 { 1716 // some data types are not allowed 1717 sal_Int32 nDataType = DataType::OTHER; 1718 xField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType; 1719 1720 sal_Bool bIllegalType = sal_False; 1721 switch ( nDataType ) 1722 { 1723 case DataType::BLOB: 1724 case DataType::LONGVARBINARY: 1725 case DataType::BINARY: 1726 case DataType::VARBINARY: 1727 case DataType::OTHER: 1728 bIllegalType = sal_True; 1729 break; 1730 } 1731 1732 if ( bIllegalType ) 1733 { 1734 _pColumn->SetObject( (sal_Int16)nFieldPos ); 1735 return; 1736 } 1737 /* 1738 // handle readonly columns 1739 sal_Bool bReadOnly = sal_True; 1740 xField->getPropertyValue( FM_PROP_ISREADONLY ) >>= bReadOnly; 1741 _pColumn->SetReadOnly( bReadOnly ); 1742 */ 1743 } 1744 1745 // the control type is determined by the ColumnServiceName 1746 static ::rtl::OUString s_sPropColumnServiceName( RTL_CONSTASCII_USTRINGPARAM( "ColumnServiceName" ) ); 1747 if ( !::comphelper::hasProperty( s_sPropColumnServiceName, _rxColumnModel ) ) 1748 return; 1749 1750 _pColumn->setModel( _rxColumnModel ); 1751 1752 ::rtl::OUString sColumnServiceName; 1753 _rxColumnModel->getPropertyValue( s_sPropColumnServiceName ) >>= sColumnServiceName; 1754 1755 sal_Int32 nTypeId = getColumnTypeByModelName( sColumnServiceName ); 1756 _pColumn->CreateControl( nFieldPos, xField, nTypeId ); 1757 } 1758 1759 //------------------------------------------------------------------------------ 1760 void FmGridControl::InitColumnsByFields(const Reference< ::com::sun::star::container::XIndexAccess >& _rxFields) 1761 { 1762 if ( !_rxFields.is() ) 1763 return; 1764 1765 // Spalten initialisieren 1766 Reference< XIndexContainer > xColumns( GetPeer()->getColumns() ); 1767 Reference< XNameAccess > xFieldsAsNames( _rxFields, UNO_QUERY ); 1768 1769 // Einfuegen muss sich an den Column Positionen orientieren 1770 for (sal_Int32 i = 0; i < xColumns->getCount(); i++) 1771 { 1772 DbGridColumn* pCol = GetColumns().GetObject(i); 1773 OSL_ENSURE(pCol,"No grid column!"); 1774 if ( pCol ) 1775 { 1776 Reference< XPropertySet > xColumnModel; 1777 ::cppu::extractInterface( xColumnModel, xColumns->getByIndex( i ) ); 1778 1779 InitColumnByField( pCol, xColumnModel, xFieldsAsNames, _rxFields ); 1780 } 1781 } 1782 } 1783 1784 //------------------------------------------------------------------------------ 1785 void FmGridControl::HideColumn(sal_uInt16 nId) 1786 { 1787 DbGridControl::HideColumn(nId); 1788 1789 sal_uInt16 nPos = GetModelColumnPos(nId); 1790 if (nPos == (sal_uInt16)-1) 1791 return; 1792 1793 DbGridColumn* pColumn = GetColumns().GetObject(nPos); 1794 if (pColumn->IsHidden()) 1795 GetPeer()->columnHidden(pColumn); 1796 1797 if (nId == m_nMarkedColumnId) 1798 m_nMarkedColumnId = (sal_uInt16)-1; 1799 } 1800 // ----------------------------------------------------------------------------- 1801 sal_Bool FmGridControl::isColumnSelected(sal_uInt16 /*nId*/,DbGridColumn* _pColumn) 1802 { 1803 OSL_ENSURE(_pColumn,"Column can not be null!"); 1804 sal_Bool bSelected = sal_False; 1805 // if the column which is shown here is selected ... 1806 Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(GetPeer()->getColumns(), UNO_QUERY); 1807 if ( xSelSupplier.is() ) 1808 { 1809 Reference< ::com::sun::star::beans::XPropertySet > xColumn; 1810 xSelSupplier->getSelection() >>= xColumn; 1811 bSelected = (xColumn.get() == _pColumn->getModel().get()); 1812 } 1813 return bSelected; 1814 } 1815 1816 //------------------------------------------------------------------------------ 1817 void FmGridControl::ShowColumn(sal_uInt16 nId) 1818 { 1819 DbGridControl::ShowColumn(nId); 1820 1821 sal_uInt16 nPos = GetModelColumnPos(nId); 1822 if (nPos == (sal_uInt16)-1) 1823 return; 1824 1825 DbGridColumn* pColumn = GetColumns().GetObject(nPos); 1826 if (!pColumn->IsHidden()) 1827 GetPeer()->columnVisible(pColumn); 1828 1829 // if the column which is shown here is selected ... 1830 if ( isColumnSelected(nId,pColumn) ) 1831 markColumn(nId); // ... -> mark it 1832 } 1833 1834 //------------------------------------------------------------------------------ 1835 sal_Bool FmGridControl::selectBookmarks(const Sequence< Any >& _rBookmarks) 1836 { 1837 vos::OGuard aGuard( Application::GetSolarMutex() ); 1838 // need to lock the SolarMutex so that no paint call disturbs us ... 1839 1840 if ( !m_pSeekCursor ) 1841 { 1842 DBG_ERROR( "FmGridControl::selectBookmarks: no seek cursor!" ); 1843 return sal_False; 1844 } 1845 1846 const Any* pBookmark = _rBookmarks.getConstArray(); 1847 const Any* pBookmarkEnd = pBookmark + _rBookmarks.getLength(); 1848 1849 SetNoSelection(); 1850 1851 sal_Bool bAllSuccessfull = sal_True; 1852 try 1853 { 1854 for (; pBookmark != pBookmarkEnd; ++pBookmark) 1855 { 1856 // move the seek cursor to the row given 1857 if (m_pSeekCursor->moveToBookmark(*pBookmark)) 1858 SelectRow( m_pSeekCursor->getRow() - 1); 1859 else 1860 bAllSuccessfull = sal_False; 1861 } 1862 } 1863 catch(Exception&) 1864 { 1865 DBG_ERROR("FmGridControl::selectBookmarks: could not move to one of the bookmarks!"); 1866 return sal_False; 1867 } 1868 1869 return bAllSuccessfull; 1870 } 1871 1872 //------------------------------------------------------------------------------ 1873 Sequence< Any> FmGridControl::getSelectionBookmarks() 1874 { 1875 // lock our update so no paint-triggered seeks interfere ... 1876 SetUpdateMode(sal_False); 1877 1878 sal_Int32 nSelectedRows = GetSelectRowCount(), i = 0; 1879 Sequence< Any> aBookmarks(nSelectedRows); 1880 if ( nSelectedRows ) 1881 { 1882 Any* pBookmarks = (Any*)aBookmarks.getArray(); 1883 1884 // (I'm not sure if the problem isn't deeper : The szenario : a large table displayed by a grid with a 1885 // thread-safe cursor (dBase). On loading the sdb-cursor started a counting thread. While this counting progress 1886 // was running, I tried do delete 3 records from within the grid. Deletion caused a SeekCursor, which did a 1887 // m_pSeekCursor->moveRelative and a m_pSeekCursor->getPosition. 1888 // Unfortunally the first call caused a propertyChanged(RECORDCOUNT) which resulted in a repaint of the 1889 // navigation bar and the grid. The latter itself will result in SeekRow calls. So after (successfully) returning 1890 // from the moveRelative the getPosition returns an invalid value. And so the SeekCursor fails. 1891 // In the consequence ALL parts of code where two calls to the seek cursor are done, while the second call _relys_ on 1892 // the first one, should be secured against recursion, with a broad-minded interpretion of "recursion" : if any of these 1893 // code parts is executed, no other should be accessible. But this sounds very difficult to achieve .... 1894 // ) 1895 1896 // The next problem caused by the same behaviuor (SeekCursor causes a propertyChanged) : when adjusting rows we implicitly 1897 // change our selection. So a "FirstSelected(); SeekCursor(); NextSelected();" may produce unpredictable results. 1898 // That's why we _first_ collect the indicies of the selected rows and _then_ their bookmarks. 1899 long nIdx = FirstSelectedRow(); 1900 while (nIdx >= 0) 1901 { 1902 // (we misuse the bookmarks array for this ...) 1903 pBookmarks[i++] <<= (sal_Int32)nIdx; 1904 nIdx = NextSelectedRow(); 1905 } 1906 DBG_ASSERT(i == nSelectedRows, "FmGridControl::DeleteSelectedRows : could not collect the row indicies !"); 1907 1908 for (i=0; i<nSelectedRows; ++i) 1909 { 1910 nIdx = ::comphelper::getINT32(pBookmarks[i]); 1911 if (IsInsertionRow(nIdx)) 1912 { 1913 // leerzeile nicht loeschen 1914 aBookmarks.realloc(--nSelectedRows); 1915 SelectRow(nIdx,sal_False); // selection aufheben fuer leerzeile 1916 break; 1917 } 1918 1919 // Zunaechst den DatenCursor auf den selektierten Satz pos. 1920 if (SeekCursor(nIdx)) 1921 { 1922 GetSeekRow()->SetState(m_pSeekCursor, sal_True); 1923 1924 pBookmarks[i] = m_pSeekCursor->getBookmark(); 1925 } 1926 #ifdef DBG_UTIL 1927 else 1928 DBG_ERROR("FmGridControl::DeleteSelectedRows : a bookmark could not be determined !"); 1929 #endif 1930 } 1931 } 1932 SetUpdateMode(sal_True); 1933 1934 // if one of the SeekCursor-calls failed .... 1935 aBookmarks.realloc(i); 1936 1937 // (the alternative : while collecting the bookmarks lock our propertyChanged, this should resolve both our problems. 1938 // but this would be incompatible as we need a locking flag, then ...) 1939 1940 return aBookmarks; 1941 } 1942 // ----------------------------------------------------------------------------- 1943 namespace 1944 { 1945 ::rtl::OUString getColumnPropertyFromPeer(FmXGridPeer* _pPeer,sal_Int32 _nPosition,const ::rtl::OUString& _sPropName) 1946 { 1947 ::rtl::OUString sRetText; 1948 if ( _pPeer && _nPosition != -1) 1949 { 1950 Reference<XIndexContainer> xIndex = _pPeer->getColumns(); 1951 if ( xIndex.is() && xIndex->getCount() > _nPosition ) 1952 { 1953 Reference<XPropertySet> xProp; 1954 xIndex->getByIndex( _nPosition ) >>= xProp; 1955 if ( xProp.is() ) 1956 xProp->getPropertyValue( _sPropName ) >>= sRetText; 1957 } 1958 } 1959 return sRetText; 1960 } 1961 } 1962 // Object data and state ------------------------------------------------------ 1963 ::rtl::OUString FmGridControl::GetAccessibleObjectName( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const 1964 { 1965 ::rtl::OUString sRetText; 1966 switch( _eObjType ) 1967 { 1968 case ::svt::BBTYPE_BROWSEBOX: 1969 if ( GetPeer() ) 1970 { 1971 Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY); 1972 if ( xProp.is() ) 1973 xProp->getPropertyValue(FM_PROP_NAME) >>= sRetText; 1974 } 1975 break; 1976 case ::svt::BBTYPE_COLUMNHEADERCELL: 1977 sRetText = getColumnPropertyFromPeer( 1978 GetPeer(), 1979 GetModelColumnPos( 1980 sal::static_int_cast< sal_uInt16 >(_nPosition)), 1981 FM_PROP_LABEL); 1982 break; 1983 default: 1984 sRetText = DbGridControl::GetAccessibleObjectName(_eObjType,_nPosition); 1985 } 1986 return sRetText; 1987 } 1988 // ----------------------------------------------------------------------------- 1989 1990 ::rtl::OUString FmGridControl::GetAccessibleObjectDescription( ::svt::AccessibleBrowseBoxObjType _eObjType,sal_Int32 _nPosition ) const 1991 { 1992 ::rtl::OUString sRetText; 1993 switch( _eObjType ) 1994 { 1995 case ::svt::BBTYPE_BROWSEBOX: 1996 if ( GetPeer() ) 1997 { 1998 Reference<XPropertySet> xProp(GetPeer()->getColumns(),UNO_QUERY); 1999 if ( xProp.is() ) 2000 { 2001 xProp->getPropertyValue(FM_PROP_HELPTEXT) >>= sRetText; 2002 if ( !sRetText.getLength() ) 2003 xProp->getPropertyValue(FM_PROP_DESCRIPTION) >>= sRetText; 2004 } 2005 } 2006 break; 2007 case ::svt::BBTYPE_COLUMNHEADERCELL: 2008 sRetText = getColumnPropertyFromPeer( 2009 GetPeer(), 2010 GetModelColumnPos( 2011 sal::static_int_cast< sal_uInt16 >(_nPosition)), 2012 FM_PROP_HELPTEXT); 2013 if ( !sRetText.getLength() ) 2014 sRetText = getColumnPropertyFromPeer( 2015 GetPeer(), 2016 GetModelColumnPos( 2017 sal::static_int_cast< sal_uInt16 >(_nPosition)), 2018 FM_PROP_DESCRIPTION); 2019 2020 break; 2021 default: 2022 sRetText = DbGridControl::GetAccessibleObjectDescription(_eObjType,_nPosition); 2023 } 2024 return sRetText; 2025 } 2026 // ----------------------------------------------------------------------------- 2027 void FmGridControl::Select() 2028 { 2029 DbGridControl::Select(); 2030 // ... betrifft das unsere Spalten ? 2031 const MultiSelection* pColumnSelection = GetColumnSelection(); 2032 2033 sal_uInt16 nSelectedColumn = 2034 pColumnSelection && pColumnSelection->GetSelectCount() 2035 ? sal::static_int_cast< sal_uInt16 >( 2036 ((MultiSelection*)pColumnSelection)->FirstSelected()) 2037 : SAL_MAX_UINT16; 2038 // die HandleColumn wird nicht selektiert 2039 switch (nSelectedColumn) 2040 { 2041 case SAL_MAX_UINT16: break; // no selection 2042 case 0 : nSelectedColumn = SAL_MAX_UINT16; break; 2043 // handle col can't be seledted 2044 default : 2045 // get the model col pos instead of the view col pos 2046 nSelectedColumn = GetModelColumnPos(GetColumnIdFromViewPos(nSelectedColumn - 1)); 2047 break; 2048 } 2049 2050 if (nSelectedColumn != m_nCurrentSelectedColumn) 2051 { 2052 // VOR dem Aufruf des select am SelectionSupplier ! 2053 m_nCurrentSelectedColumn = nSelectedColumn; 2054 2055 if (!m_bSelecting) 2056 { 2057 m_bSelecting = sal_True; 2058 2059 try 2060 { 2061 Reference< XIndexAccess > xColumns(GetPeer()->getColumns(), UNO_QUERY); 2062 Reference< XSelectionSupplier > xSelSupplier(xColumns, UNO_QUERY); 2063 if (xSelSupplier.is()) 2064 { 2065 if (nSelectedColumn != SAL_MAX_UINT16) 2066 { 2067 Reference< XPropertySet > xColumn; 2068 ::cppu::extractInterface(xColumn,xColumns->getByIndex(nSelectedColumn)); 2069 xSelSupplier->select(makeAny(xColumn)); 2070 } 2071 else 2072 { 2073 xSelSupplier->select(Any()); 2074 } 2075 } 2076 } 2077 catch(Exception&) 2078 { 2079 } 2080 2081 2082 m_bSelecting = sal_False; 2083 } 2084 } 2085 } 2086 // ----------------------------------------------------------------------------- 2087 sal_Int32 FmGridControl::GetSelectedColumn() const 2088 { 2089 return m_nCurrentSelectedColumn; 2090 } 2091 // ----------------------------------------------------------------------------- 2092 void FmGridControl::KeyInput( const KeyEvent& rKEvt ) 2093 { 2094 sal_Bool bDone = sal_False; 2095 const KeyCode& rKeyCode = rKEvt.GetKeyCode(); 2096 if ( IsDesignMode() 2097 && !rKeyCode.IsShift() 2098 && !rKeyCode.IsMod1() 2099 && !rKeyCode.IsMod2() 2100 && GetParent() ) 2101 { 2102 switch ( rKeyCode.GetCode() ) 2103 { 2104 case KEY_ESCAPE: 2105 GetParent()->GrabFocus(); 2106 bDone = sal_True; 2107 break; 2108 case KEY_DELETE: 2109 if ( GetSelectColumnCount() && GetPeer() && m_nCurrentSelectedColumn >= 0 ) 2110 { 2111 Reference< ::com::sun::star::container::XIndexContainer > xCols(GetPeer()->getColumns()); 2112 if ( xCols.is() ) 2113 { 2114 try 2115 { 2116 if ( m_nCurrentSelectedColumn < xCols->getCount() ) 2117 { 2118 Reference< XInterface > xCol; 2119 xCols->getByIndex(m_nCurrentSelectedColumn) >>= xCol; 2120 xCols->removeByIndex(m_nCurrentSelectedColumn); 2121 ::comphelper::disposeComponent(xCol); 2122 } 2123 } 2124 catch(const Exception&) 2125 { 2126 OSL_ENSURE(0,"exception occured while deleting a column"); 2127 } 2128 } 2129 } 2130 bDone = sal_True; 2131 break; 2132 } 2133 } 2134 if ( !bDone ) 2135 DbGridControl::KeyInput( rKEvt ); 2136 } 2137 // ----------------------------------------------------------------------------- 2138 2139 2140 2141